Database Tiers

Gigalixir offers two tiers of databases: free and standard.

Free Tier databases are not suitable for production use. We provide them to users to help them get their development started.

Free tier databases run on a multi-tenant postgres database cluster with shared CPU, memory, and disk. You are limited to two connections, 10,000 rows, and no automatic backups. Idle connections are terminated after five minutes.

Free tier databases attached to applications that are inactive for an extended period of time will be destroyed.

Standard Tier database are production quality databases. High availability and read replicas are available. Backups are automatic and daily. Connection limits are much higher. Disk size scales with your usage.

See Database Tier Comparison for more details.

Continue reading for general information applicable to both tiers.
For more information on creating, managing, and operating databases, see:

Connecting to a Database

If you followed the Getting Started Guide, then your database should already be connected. If not, connecting to a database is done no differently from apps running outside Gigalixir.

We recommend you set a DATABASE_URL config and configure your database adapter accordingly. In short, you’ll want to add something like this to your prod exs file.

config :gigalixir_getting_started, GigalixirGettingStarted.Repo,
  adapter: Ecto.Adapters.Postgres,
  url: {:system, "DATABASE_URL"},
  database: "",
  ssl: true,
  pool_size: 2

Replace :gigalixir_getting_started and GigalixirGettingStarted with your app name. Then, be sure to set your DATABASE_URL config.

For more information on setting configs, see How to Configure an App. If you provisioned your database using the Gigalixir Console or CLI, then DATABASE_URL should be set for you automatically once the database is provisioned.

Otherwise, do the following:

gigalixir config:set DATABASE_URL="ecto://{user}:{pass}@{host}:{port}/{db}"

Runnning Migrations

We try to make it easy by providing a special command. The command runs on your existing app container, so you’ll need to make sure your app is running first and set up your SSH keys.

gigalixir account:ssh_keys:add "$(cat ~/.ssh/id_rsa.pub)"

Then run:

gigalixir ps:migrate

This command runs your migrations in a Remote Console directly on your production node. It makes some assumptions about your project so if it does not work, please contact us for help.

Umbrella App Migrations

If you are running an Umbrella app, you will probably need to specify which “inner app” within your Umbrella to migrate. Do this by passing the --migration_app_name flag like so

gigalixir ps:migrate --migration_app_name=$MIGRATION_APP_NAME

When running gigalixir ps:migrate, sometimes the migration doesn’t do exactly what you want. If you need to tweak the migration command to fit your situation, it helps to know that all gigalixir ps:migrate is doing is dropping into a remote_console and running the following:

repo = List.first(Application.get_env(:gigalixir_getting_started, :ecto_repos))
app_dir = Application.app_dir(:gigalixir_getting_started, "priv/repo/migrations")
Ecto.Migrator.run(repo, app_dir, :up, all: true)

For information on how to open a Remote Console, see How to Drop into a Remote Console.

For example if you have more than one app, you may not want to use List.first to find the app that contains the migrations.

Chicken Egg Migration Problems

If you have a chicken-and-egg problem where your app will not start without migrations run, and migrations won’t run without an app running, you can try the following workaround on your local development machine. This will run migrations on your production database from your local machine using your local code.

MIX_ENV=prod DATABASE_URL="$YOUR_PRODUCTION_DATABASE_URL" mix ecto.migrate

Running Migrations at Startup

Warning
Application startup has a 10 minute timeout. If your migration is rather large, then we recommend not using this technique. Consider the manual migrations listed above or running the migration from a local workstation by setting MIX_MODE to prod and setting your DATABASE_URL similar to the Chicken Egg solution.

Releases Migrations at Start

If you are using Elixir Releases, we suggest creating a custom Procfile and overlaying it into your release tarball.

To do this create a file rel/overlays/Procfile with something like this:

web: /app/bin/$GIGALIXIR_APP_NAME eval "MyApp.Release.migrate" && /app/bin/$GIGALIXIR_APP_NAME $GIGALIXIR_COMMAND

You have to implement the MyApp.Release.migrate function with something like https://hexdocs.pm/phoenix/releases.html#ecto-migrations-and-custom-commands.

You might also be interested in reading https://elixirforum.com/t/equivalent-to-distillerys-boot-hooks-in-mix-release-elixir-1-9/23431

Mix Migrations at Start

If you aren’t running Elixir Releases or Distillery, meaning you are in Mix mode, you can try modifying your Procfile to something like this

web: mix ecto.migrate && elixir --name $MY_NODE_NAME --cookie $MY_COOKIE -S mix phx.server

For more details, see Can I Use a Custom Procfile?

Distillery Migrations at Start

If you are using Distillery, we suggest using a Distillery pre-start boot hook by following https://github.com/bitwalker/distillery/blob/master/docs/guides/running_migrations.md and https://github.com/bitwalker/distillery/blob/master/docs/extensibility/boot_hooks.md

Reset a Database

Drop into a Remote Console and run this to “down” migrate. You may have to tweak the command depending on what your app is named and if you’re running an umbrella app.

Ecto.Migrator.run(MyApp.Repo, Application.app_dir(:my_app, "priv/repo/migrations"), :down, [all: true])

Then run this to “up” migrate.

Ecto.Migrator.run(MyApp.Repo, Application.app_dir(:my_app, "priv/repo/migrations"), :up, [all: true])

Seeding a Database

If you are in Mix mode (not using Distillery or Elixir releases) and have a seeds.exs file, you can just run

gigalixir run -- mix run priv/repo/seeds.exs

Otherwise, you’ll need to drop into a Remote Console and run commands manually. If you have a seeds.exs file, you can follow the Distillery Migration Guide and run something like this in your Remote Console.

seed_script = Path.join(["#{:code.priv_dir(:myapp)}", "repo", "seeds.exs"])
Code.eval_file(seed_script)

Manual Backups

For point in time backup or migration of data, we recommend pg_dump.

You can find all the connection parameters you need from gigalixir pg.

This should dump the database contents as a sql file which you can load back in with psql.

If you dump a binary file, then you can use pg_restore.

Tier Comparison

Database Feature FREE Tier STANDARD Tier
SSL Connections YES YES
Data Import/Export YES YES
Data Encryption   YES
Dedicated CPU   YES[1]
Dedicated Memory   YES
Dedicated Disk   YES
No Connection   YES
High Availability   YES[2]
Read Replicas Available   YES
Limits No   YES
Row Limits   YES
Backups   YES
Scalable/Upgradeable   YES
Automatic Data Migration   YES
Extensions   YES
Functions   YES
Triggers   YES
Role Management   YES
  • [1] Standard databases with size 4 and above have dedicated CPU.
  • [2] Standard databases default to single instance, but can have high availability enabled.