Creating and migrating a devise-driven User model in a main/replica context
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
When developing applications with high availability and scalability in mind, it becomes necessary to consider architectures beyond a single database. One common setup is having a main database (also known as primary or master) and one or more replica (slave) databases. This article will guide you through creating and migrating a User model in a Ruby on Rails application using the Devise gem in a main/replica database context.
Understanding Main/Replica Architecture
In a main/replica setup, the main database handles all write operations, while the replica handles read operations. This architecture helps in load distribution and increases read throughput, which is especially beneficial for read-heavy applications.
Setting Up Devise
Devise is a flexible authentication solution for Rails based on Warden. It provides a comprehensive suite of features and is easy to integrate and customize. To begin, add Devise to your Gemfile:
Run bundle install to install the gem. After that, you need to set up Devise in your Rails application:
This command creates the necessary configuration files and initializer under config/initializers/devise.rb.
Creating the User Model
Now, generate your User model using Devise:
This command constructs the model with default modules such as database authenticatable, registerable, recoverable, rememberable, trackable, and confirmable. Also, it automatically creates a migration file for the users table.
Configuring Database.yml
Your database.yml needs to reflect your main/replica setup. For instance:
Implementing Read/Write Split
To implement read/write split in Rails, you can use the active_record_slave gem or similar plugins which provide a mechanism to direct read queries to the replica. However, from Rails 6 onwards, you can also utilize the built-in Role and Sharding support to direct traffic to the appropriate database:
Handling Migrations
Migrations should always be run against the main database because the replica is typically read-only and receives updates via replication from the main database. Ensure that your migration scripts and Rails environment are configured to connect to the primary database when performing these migrations.
This command ensures that Rails connects to the primary database as specified in the database.yml.
Summary Table of Key Components
| Component | Description | Rails Command / Code |
| Devise Setup | Adding user authentication system to Rails. | rails generate devise:install |
| User Model | Creating the user model using Devise. | rails generate devise User |
| Database Config | Setting up YAML configuration for main/replica. | Edit config/database.yml |
| Read/Write Split | Configuring application to handle database roles. | connects_to database: {writing: :primary, reading: :replica} |
| Migrations | Running migrations on the main database. | RAILS_ENV=production bin/rails db:migrate |
Additional Considerations
- Error Handling: Implement robust error handling to address any connection issues with the replica.
- Monitoring and Failover: Set up monitoring for the databases and have a plan for failover in case the primary database goes down.
By following these steps, you can effectively set up and manage a Devise-driven User model in a main/replica database architecture, allowing your Rails application to scale efficiently while maintaining robust data integrity and availability.

