Implement Read Replica Database on Rails 6 101

Full instructions at the read-replicas work and implement

William
WilliamDesk
4 min readFeb 20, 2022

--

Recap

For Rails 5, you can only use the gem (e.g. multi_db) to reach your goal. But on Rails 6, has full support for multiple databases with Active Record, which means if you have read replica at your database (e.g. Amazon RDS Read Replicas ), you can simply use it.

You can see the Rails official guideline to know how it is.

The difference between Rails 6.0 and Rails 6.1

Some of the good articles can show the future as an example.

We will use Rails 6.1 for example to implement the read replica mechanism.

Step 1: Setup your database.yml

Step 2: Modify your application_record.rb file

2.1 Use the Rails default mechanism to control the switch.

Rails framework takes a very special way to switch the database that the project uses. Unlike common frameworks, it controls at the Model and Database layer, if the SQL statement is CREATE , UPDATE , DELETE , it will switch to the write database; and SELECT go for the read-replica database.

Rails way is:

  • Using writing (primary) database if the API request method is POST, PUT, DELETE, or PATCH .
  • Using read-replica (read-only) database if the API request method is GET or HEAD .
  • Rails guarantees “read your own write” and will send your GET or HEAD request to the writer if it’s within the delay window. By default, the delay is set to 2 seconds.

If your application has the config setting api_only = true, you can not using the multi-db mechanism.
https://github.com/rails/rails/issues/41932

All you need to do is add the configs below to your environment config file or the application file.

2.2. Do your own control to switch the database by role

We set the role before, using the “writing” role means using a primary database; and using the “reading” role means using the primary-replica database.

We can easily switch the role by inside the block:

Based on the role, you can do your own switch control at the controller by around_action.

Step 3: Test all situation

Test case 1: mix-use situation

Test case 2: Is rake cron job using the primary database?

Sometimes we use the gem whenever to implement the corn job, the test result is: “Yes, it uses the primary database at background job”.

Test case 3: Is the sidekiq worker job using the primary database?

Sidekiq is a simple, efficient background processing for Ruby. The test result is: “Yes, it uses the primary database at background job”.

Points of test case:
1. Use the instance variable for which variable you will continue to use.
2.
Not to frequently switch the role at the same API request, recommend to control by around_action instead.
3. Need to
consider databases sync delay time.
4.
Background job (e.g. sidekiq) uses the primary database.

Step 4: Check all routes of GET and HEAD API

We are very familiar with the project that we created, but how about the gems you installed?

Some of the gems have their own routes and controllers, they may use the GET or HEAD method for updating records.

For example, the gem ahoy_email has 2 GET API and update the data to record the mail’s opening time and URL click time.

We can easily check the rails routes command and their source code.

The rails routes show the 2 GET methods from ahoy_email gem

Here is a part of the source code:

ahoy_email gem’s controller source code. (screenshot at 2022/02/20)

It may cause the ActiveRecord::ReadOnlyError. We need to refactor these 2 APIs. Here is the solution:

You may need to know what is the Rails Engines to modify it.
https://guides.rubyonrails.org/engines.html

Before deploying to the production, I recommend deploying the project to the preparing or sandbox environment for a week first, checking it all works fine, and not capturing any errors like ActiveRecord::ReadOnlyError by Sentry.

Hope this article will help you implement the read-replica database well. If bits of any help, please click the clap let me know. :)

--

--