Read replicas databases offer a range of advantages that bolster database performance, availability, and scalability. You can have an unlimited amount of read replicas per Standard tier database.
List Read Replicas for a Database
First you will need to get the ID for your database:
gigalixir pg
Now you can list the read replicas:
gigalixir pg:read_replicas -d $DATABASE_ID
Creating Read Replicas
Add a new read replica with:
gigalixir pg:read_replicas:create -d $DATABASE_ID
By default the read replica will have the same size as the primary.
You can specify a size on creation if you wish:
gigalixir pg:read_replicas:create -d $DATABASE_ID --size=$SIZE
Enabling High Availability
Read replicas are created as single instances. High availability can be enabled with the pg:scale command:
gigalixir pg:scale -d $DATABASE_ID --high_availability=enabled
Scaling will cause a downtime while the database restarts. See Scaling Times for details.
Equally, high availability can be disabled with:
gigalixir pg:scale -d $DATABASE_ID --high_availability=disabled
See High Availability Pricing for cost.
Scaling
After you create your read replica, you can scale it with the same command as for the primary with:
gigalixir pg:scale -d $READ_REPLICA_ID --size=$SIZE
Scaling will cause a downtime while the database restarts. See Scaling Times for details.
Standard tier databases sizes can be 0.6, 1.7, 4, 8, 16, 32, 48, 64, or 96. See Database Pricing for details.
Working with Read Replicas in Elixir
When it comes time to utilize your read replicas, Ecto makes it easy. We suggest you create a config variable for each Read Replica:
gigalixir config:set READ_REPLICA1_URL=ecto://user:pass@host:5432/database
You can get your read replica URL from the listing:
gigalixir pg:read_replicas -d $PRIMARY_DATABASE_ID
Just be sure to switch from postgresql://
to ecto://
.
Next we update our Repo module to understand there is a read replica:
# lib/fancy_app/repo.ex
defmodule FancyApp.Repo do
use Ecto.Repo,
otp_app: :fancy_app,
adapter: Ecto.Adapters.Postgres
def replica, do: FancyApp.Repo.Replica
end
defmodule FancyApp.Repo.Replica do
use Ecto.Repo,
otp_app: :fancy_app,
adapter: Ecto.Adapters.Postgres,
default_dynamic_repo: FancyApp.Repo.Replica,
read_only: true
end
Now we need to add the configuration:
# config/prod.exs (or runtime.exs, or releases.exs)
config :fancy_app, FancyApp.Repo.Replica,
ssl: true,
url: {:system, "READ_REPLICA1_URL"},
pool_size: {:system, "POOL_SIZE"},
pool_timeout: 10_000
If your read replica has a different size than your primary database,
consider using a separate config variable for the pool_size
.
Now update the application startup:
# lib/fancy_app/application.ex
def start(_type, _args) do
...
children = [
FancyApp.Repo,
FancyApp.Repo.Replica,
...
With that all done, it is time to utilize the read replica.
def list_usernames do
from(u in User, select: u.username)
|> Repo.replica().all()
end
See Ecto’s Read Replica Documenation for further details.
Strategies for Utilizing Read Replicas
Some users will setup their read replicas to perform all of their read operations, reserving the primary database for write only operations. In this scenario it can be useful to make a ReplicaPool module that will round robin requests to the various read replicas.
If you are running multiple application replicas and multiple read replicas, some users will assign a read replica to each application replica.
Another strategy for utilizing a read replica is to use the replica purely for intensive queries or long running jobs.
Read replicas can also be utilized to isolate external applications or providers to read-only operations that will not affect your primary database.
Read replicas can take a little planning, but the payoff can be huge.
Users and Roles
Read replica are exact copies of the primary database. They will contain the same users, permissions, views, etc as the primary database. Any users, roles, views, etc that you may want in the read replica will need to be setup in the primary database.
Restarting a Read Replica
If you need to restart your read replica, contact us and we’ll help you out.
Destroying Read Replicas
When you no longer need the read replica, you can destroy it with:
gigalixir pg:destroy -d $READ_REPLICA_ID
Read Replica Pricing
Size | Standard Support |
Extended Support |
RAM | Connection Limit |
---|---|---|---|---|
0.6 | $25/mo | $50/mo | 0.6 GB | 25 |
1.7 | $50/mo | $100/mo | 1.7 GB | 50 |
4 | $100/mo | $200/mo | 4 GB | 100 |
8 | $200/mo | $400/mo | 8 GB | 200 |
16 | $400/mo | $800/mo | 16 GB | 250 |
32 | $800/mo | $1600/mo | 32 GB | 300 |
48 | $1200/mo | $2400/mo | 48 GB | 350 |
64 | $1600/mo | $3200/mo | 64 GB | 400 |
96 | $2400/mo | $4800/mo | 96 GB | 500 |
See Supported Versions for more information on the support levels.
High Availability Pricing
Adding high availabilty doubles the cost of the read replica. Prices are prorated to the second. See Read Replica Pricing for the undoubled prices per size.
Scaling Times
Scaling a standard tier database requires a restart of the database. Below is a list of the typical operation times for database sizes.
Size | Typical Scaling Time |
---|---|
0.6 | 10 - 25 minutes |
1.7 | 10 - 25 minutes |
4+ | 4 - 8 minutes |