/fly-multi-region

A proto-type library for using Fly.io's Multi-Region Databases with Ecto.

Primary LanguageElixir

FlyMultiRegion

A library for using Fly.io's Multi-Region Databases with Ecto.

This library assumes that:

  • You have an app hosted on Fly.io
  • You've already created and configured read-replica databases on Fly. Refer to Fly.io's documentation for more information on how to do that.

Warning

It's likely that Fly will implement their own version of this library. So this library should serve as a proof-of-concept. There are a number of assumptions and improvements that could be made. Please use this library at your own risk and know that I never intended it to be used in production.

This library was based on what I originally implemented in this blog post

Usage

Installation

The package can be installed by adding fly_multi_region to your list of dependencies in mix.exs:

def deps do
  [
    {:fly_multi_region, "~> 0.0.1"}
  ]
end

Configuration

If you're following the Fly.io guides then your database config will happen at runtime. Add the following to the runtime.exs file:

config :fly_multi_region,
  region: System.get_env("FLY_REGION"),
  regions: ["nrt", "ord"],
  url: System.get_env("DATABASE_URL"),
  opts: [
    socket_options: [:inet6],
    pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10")
  ]

Parameters:

  • region: generated by Fly.io by default
  • regions: a list of replicas in your cluster
  • url: database url
  • opts: configuration options for Ecto

Supervision

Add FlyMultiRegion to your Application's supervision tree

As mentioned in Ecto's documentation for replica databases it's necessary to add any Repos to your supervision tree. With that in mind, make sure to add FlyMultiRegion to your Application module (application.ex)

def start(_type, _args) do
    children =
      [
        ...,
        FlyMultiRegion
      ]

    ...
    Supervisor.start_link(children, opts)
  end

Repo

Add use FlyMultiRegion.Repo to your projects main Repo module:

defmodule MyApp.Repo
  ...
  use FlyMultiRegion.Repo
end

How to use it

When ever making a read request with ecto, use .replica()

Example:

 # original
 Repo.all(User)

 # becomes
 Repo.replica().all(User)

Future Improvements

  • tests
  • make replica's more configurable (for example, the assume Postgres at the moment)
  • remove Ecto as a dependancy (it's only used to parse a database url)