PostgreSQL Row Level Security
The Rails right way to do multitenancy
Table of Contents
- Required Installations
- Code of Conduct
- Show your support
It's time we start doing multitenancy right! You can avoid creating a separate Postgres schema/databases for each customer or trying to ensure the WHERE clause of every single query includes the particular company. Just integrate PgRls seamlessly to your application.
This gem will integrate PostgreSQL RLS to help you develop a great multitenancy application.
Add this line to your application's Gemfile:
And then execute:
$ bundle install
Or install it yourself with:
$ gem install pg_rls
rails generate pg_rls:install company #=> where company eq tenant model name
You can change company to anything you'd like, for example,
This will generate the model and inject all the required code
For any new model that needs to be under rls, you can generate it by writing
rails generate pg_rls user #=> where user eq model name
and it will generate all the necesary information for you.
You can swtich to another tenant by using
PgRls::Tenant.switch :app #=> where app eq tenant name
Don't forget to update how you want
PgRls to find your tenant, you can set multiple options by modifying
You can add the following configuration to your Database Config File to improve performance and remove
# app/config/database.yml <% def db_username return PgRls.username unless ENV['AS_DB_ADMIN'] Rails.application.credentials.dig(:database, :server_1, :username) end %> ... development: <<: *default database: example_development username: <%= db_username %> # Apply this to production and all env including tests ...
If you are getting
PG::InsufficientPrivilege: ERROR: permission denied you can override does permistion by running
RAILS_ENV=test rake db:grant_usage
Many application uses some sort of database cleaner before running thair spec so on each test that we run we'll have an empty state. Usually, those gems clear our user configuration for the database. To solve this issue, we must implement the following:
# spec/rails_helper.rb ... # some database cleaning strategy config.before(:suite) do # Create the tenant which in this example is company and we are using FactoryBot FactoryBot.create(:company, subdomain: 'app') # In this default case our initializer is set to search by subdomain so will use it PgRls::Tenant.switch :app end ...
After checking out the repo, run
bin/setup to install dependencies. Then, run
rake spec to run the tests. You can also run
bin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run
bundle exec rake install. To release a new version, update the version number in
version.rb, and then run
bundle exec rake release, which will create a git tag for the version, push git commits and the created tag, and push the
.gem file to rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/dandush03/pg_rls. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
The gem is available as open source under the terms of the MIT License.
Code of Conduct
Everyone interacting in the PgRls project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.
Currently we only support subdomain as a searcher but will soon integrate slug/domain and cookies support we recommed the use of ``
Show your support
Give a ⭐️ if you like this project!
If this project help you reduce time to develop, you can give me a cup of coffee :)