Streamlining Your Rails 8 App: Migrating from Postgres to SQLite
Simplify your Rails 8 stack by transitioning from Postgres to SQLite for better efficiency and reduced complexity
With Rails 8’s shift to SQLite as the new default database, developers now have the opportunity to simplify their application stack while retaining power and flexibility.
SQLite’s recent improvements for Rails make it a great option for production use. After all SQLite, which was initially released in 2004, has come a long way and is now a powerful, reliable, and performant database engine – perfect for many applications. With the Rails 8 release, SQLite has become the default database for new Rails applications, and comes with a host of performance tuning by default.
In this guide, I describe how to migrate an existing Rails 8 app from Postgres to SQLite to supercharge your application, while at the same time compressing your stack. Keep in mind that the process I describe below requires some downtime, so plan accordingly.
In the application I’m migrating, I’m using Rails 8 and Kamal for deployment. If you’re using a different deployment tool, the steps might be different.
Create a Backup of the Postgres Database
Before migrating your Rails application from Postgres to SQLite, it’s essential to create a backup of your Postgres database. This backup will ensure that you have a copy of your data in case anything goes wrong during the migration process.
In my case, Postgres is running in a Docker container. First, let’s access the Postgres container using the following command:
Next, create a backup of the Postgres database using the pg_dump
command:
This command will create a dump of the Postgres database in the file database.dump
. Now, exit the Docker container. You can copy this file to the host machine using the following command:
To also download the dump file from the server to your local machine, you can use the scp
command:
Now, you have a backup of your Postgres database. You can use this backup to restore the data if the migration process fails.
Update the Rails Configuration
Ensure your application has been upgraded to Rails 8 before continuing. In order to point your Rails application to the SQLite database, you need to update the database configuration in the config/database.yml
file. This is how the configuration used to look like with Postgres:
And with SQLite, the configuration will look like this:
Deploy with the New Configuration
Now, we can deploy the updated Rails application. In the app I’m migrating, I’m using Kamal. If you’re using something else, be sure to re-deploy your application so the new configuration is loaded in your application. When starting for the first time, the Rails Docker entrypoint will create the production SQLite database and prepare it for use (via bin/rails db:prepare
, which will set up and migrate the database).
Verify on the server that the SQLite database has been created and the application is running as expected.
This should list the SQLite database file named production.sqlite3
– if it doesn’t, there might be an issue with the deployment. Check the logs to identify the problem.
As soon as you can see the SQLite database file, you can proceed with the next steps.
Import the Postgres Data into SQLite
Now that the Rails application is running with the (empty) SQLite database, we can import the data from Postgres. Unfortunately, there is no direct way to import a Postgres dump into SQLite.
In my research I discovered tools like pg2sqlite, but they fail to correctly prepare the SQLite database with the required column data types and constraints. It’s best to start from a “clean slate” and import the data separately after Rails has set up the SQLite database with the proper schema.
One option is to create a one-off migration script to connect to both the Postgres and SQLite databases and transfer the data over to the newly created SQLite database.
Below is an example script to transfer the data. You might place this file in script/migrate_data.rb
. For simple applications, this might be enough. For more complex scenarios, you might need to add additional logic to handle data transformations or relationships. Run this script while inside the container via bundle exec ruby script/migrate_data.rb
To run the import script again (e.g., after making changes), you can nuke the SQLite database and run the script again:
After importing the data, your Rails application should now be running as before with the original data from the Postgres database, but now from within SQLite! You can verify this by checking the data in the application or running queries against the SQLite database. Alternatively, download the SQLite database file to your local machine and inspect it using a SQLite database viewer.
To ensure your app is now talking to the SQLite database, you can stop the Postgres container and see if the Rails application is still running as expected.
Check the logs to confirm everything is working as expected. To tail the logs, you can using the following command:
Congrats! Your Rails application is now running on SQLite.
Adding Backups with Litestream
To ensure that your SQLite database is backed up regularly, you might rely on Litestream. Litestream is a tool that continuously backs up SQLite databases to cloud storage providers like AWS S3. For this, we can use the handy litestream-ruby
gem. Read about how to install and configure it in the GitHub repository.
Stopping accessory and cleaning up
After you’ve confirmed that your Rails application is running smoothly with the SQLite database, you can stop the Postgres container and clean up the volumes. Here are the steps to do so:
To identify the volume name, you can use docker volume ls
. Then, remove the volume using the following command:
Alternatively, use Kamal to remove the Postgres accessory:
Also, don’t forget to…
- Remove the
pg
gem from yourGemfile
- Remove
libpq-dev
and other no longer needed Postgres-related dependencies from the Dockerfile - Remove the Postgres acessory from the Kamal
deploy.yml
file, if applicable - Remove any Postgres-related secrets from Kamal secrets, if applicable
- Remove the migration script and the Postgres dump file
Conclusion
By migrating your Rails 8 application from Postgres to SQLite, you’ve simplified your setup while maintaining performance and reliability. SQLite’s integration with Rails 8 offers a straightforward, efficient solution for many use cases.
With proper backup strategies in place, you can confidently rely on SQLite in production. Following the steps outlined in this guide, your Rails app is now running smoothly on SQLite.