1/ What is the proper way to let a single-DB Heroku Rails 7 app start accessing a follower DB after it has been provisioned in Heroku? I understand we can continue to get the config of the leader DB from the DATABASE_URL
environment variable; as for the replica/follower database, should we specify its URL manually like below? One issue I see is that the environment variable name will change when upgrading the DB (see point 2 below).
# config/database.yml
production:
primary:
adapter: postgresql
# no URL specified: use DATABASE_URL
primary_replica:
adapter: postgresql
url: <%= ENV["HEROKU_POSTGRESQL_XXX_URL"] %>
replica: true
Is there anything else we should know, e.g. should we start to use different Rails commands when running migrations, or specifying database users somewhere? (Not really, if I understand the guide correctly?)
2/ Once such a follower starts being accessed by the app, how to upgrade the leader and follower databases when a new Postgresql version becomes available? I understand that usually this is done by follower changeover. Should the procedure be like below?
- In Heroku, provision a first new follower with the latest Postgresql version (
heroku addons:create
) - In Heroku, place the app in maintenance mode (
heroku ps:scale worker=0
+heroku maintenance:on
) - In Heroku, promote A to become the primary (
heroku pg:unfollow
+heroku pg:promote
) - In Heroku, provision a second new follower with the latest Postgresql version (
heroku addons:create
) - In Rails, update
config/database.yml
>primary_replica
>url
to use the new DB URL of this second follower, deploy the change - In Heroku, disable maintenance mode (
heroku ps:scale worker=1
,heroku maintenance:off
) - After checking everything in the app works as expected, decommission the 2 previous databases (
heroku addons:destroy
)
We are interested in this to protect against writing to the DB for operations that should be read-only, such as when running reports (*) or simply displaying content, and to reduce the load on the primary DB. I suppose there can be a lot of edge cases in deciding which DB should be accessed as sometimes a DB might be modified even in GET requests (e.g. to store some analytics/logs), so at first we would be satisfied with always using the primary DB, and only accessing the follower when manually specified.
(*) As suggested in the Blazer gem for instance.