Transcript

Multi-tenancy in Rails with PostgreSQL

Schemas

Tomasz Giereś

● Tomasz Giereś● tomaszgieres (github/twitter)● tomasz.gieres@gmail.com● almost 2 years at Lunar Logic● mainly developing Ruby on Rails

applications● also AngularJS, Backbone, Chef, bash,

anything needed● 10+ projects● work with clients

Me

● 50 lines of source code,● 1 meme,● 45 slides,● 30-40 minutes,● ask questions during the presentation,● feedback welcome

This talk and presentation

Meme

schema != schema.rb

The problem

1. You have a blog.2. Your friend wants a blog too.

Multiple instances

Multiple instances

1. Rent an another server / create new heroku application / whatever,

2. Buy a domain,3. Configure everything,4. Deploy a copy of the blog engine there.

Multiple instances

● Very easy at the beginning,● fixed price per instance* (server / hardware /

database / licences / external services ),● $100 to host a blog with 50 000 UU for you,● $100 to host a blog with 5 UU for your friend,● $100 dollars for every new instance,● deploy, administrate, backup separately,● separate admin panels etc., no easy way to

i.e. collect data from several applications

* Instance = application process(es) + database + (...)

Multiple instances

Multitenancy

Multitenancy

● One application instance serves all the blogs,

● One database for all the blogs,● No need to pay for the external services

separately?,● Easier to scale:

○ count traffic for all the blogs,○ just add more heroku dynos or application processes

when needed

Multitenancy

Multitenancy

1. Add root element to data structures:● User has a blog_id● Post has a blog_id● etc.

2. At storage and configuration level● keep the data for every tenant in a separate

storage ● dynamically switch the storage before

accessing the data

PostgreSQL schemas

● a namespace● a group of tables● an extra layer between a database and a

table● just an extra dot :)

○ <table_name>.<column_name>○ <schema_name>.<table_name>.<column_name>

PostgreSQL schemas

PostgreSQL schemas

● every tenant uses its own schema,● tables with common data are not in schemas

( in fact they are in ‘public’ schema )

PostgreSQL schemas

PostgreSQL schemas

PostgreSQL schemasanother_database=# CREATE DATABASE blogs OWNER postgres;CREATE DATABASE

blogs=# CREATE TABLE administrators (name varchar(40));CREATE TABLE

blogs=# INSERT INTO administrators (name) VALUES ('John');INSERT 0 1

PostgreSQL schemas

PostgreSQL schemasblogs=# CREATE SCHEMA rails_tips;CREATE SCHEMA

blogs=# CREATE TABLE rails_tips.posts ( title varchar(40),content text );CREATE TABLE

blogs=# INSERT INTO rails_tips.posts (title, content) VALUES ('Active Record basics', 'blah blah');INSERT 0 1

PostgreSQL schemas

PostgreSQL schemasblogs=# CREATE SCHEMA angularjs_tips;CREATE SCHEMA

blogs=# CREATE TABLE angularjs_tips.posts ( title varchar(40), content text );CREATE TABLE

blogs=# INSERT INTO angularjs_tips.posts (title, content) VALUES ('Active Record basics', 'blah blah');INSERT 0 1

PostgreSQL schemasblogs=# SELECT * FROM administrators;

name------ John(1 row)

PostgreSQL schemas

blogs=# SELECT * FROM angularjs_tips.posts;

title | content---------------+----------- Scopes basics | blah blah(1 row)

PostgreSQL schemas

Repeating schema name all the time is annyoing.

PostgreSQL schemas

united_states=# SELECT * FROM posts;

ERROR: relation "posts" does not existLINE 1: SELECT * FROM posts; ^

PostgreSQL schemas

blogs=# SHOW search_path;

search_path---------------- "$user",public(1 row)

PostgreSQL schemas

blogs=# SET search_path TO rails_tips, public;SET

blogs=# SELECT * FROM posts;

title | content----------------------+----------- Active Record basics | blah blah(1 row)

PostgreSQL schemas

Practice

Practice

● usually used with subdomains,● a client organization / a workspace / any

isolated unit = tenant ?● simpler application design and architecture,● less chance for the data leak

Practice

Rails

Wrocław

Rails

Active Record + pg gem:● supports schemas (create, drop, list),● can manipulate search path,● people prefer to execute SQL statements

anyway,● supports the same operations on the tables

within schema as on the public ones

RailsFrom Railscast:

#389 Multitenancy with PostgreSQL

with some modifications

Rails

Rails

RailsIt’s common to set search path

and current tenantin rack middleware

RailsMigrations

Rails

Useful information

● influitive / apartment (gem)● pow server● classes and methods to work in console● don’t forget about security● subdomains and schemas in testing

environment (lots of helpers needed),● rescue, sidekiq

top related