Skip to content

Hosting several customers

Kewos runs just as well for one customer on their own machine as for a hundred on a shared server. It is the same code: what changes is the number of rows in a registry.

The rule is simple and non-negotiable: one database per customer. No shared tenant_id column, no common schema. A backup restores one customer, a leak does not cross over, and a customer who leaves takes their database with them.

Adding a customer

Two steps, in this order, and the first one is yours:

Fenêtre de terminal
# 1. The database, created by the operator
createdb -O kewos kewos_library2
# 2. Registration in the registry
kewos tenant create library2 \
--database-url 'postgresql+psycopg://kewos:...@127.0.0.1:5432/kewos_library2' \
--master-url "$KEWOS_MASTER_DATABASE_URL" \
--display-name 'Northern Library'
registered tenant 'library2' -> postgresql+psycopg://kewos:***@127.0.0.1:5432/kewos_library2

Note the ***: the database password is never printed, not here, not in the listing, not in a log. A terminal gets shared, pasted into a ticket, filmed during a demo.

The registry is what the server consults to route a request to the right database. The command does not create the database: where it lives, who owns it and how it is tuned belong to the operator.

The new customer’s schema

It is empty. One command fills it, and it handles every customer:

Fenêtre de terminal
kewos reconcile --master-url ... --modules-root ... --confirm
library2 [active]: reconciled (1 migration(s), 0 column(s))
main [active]: reconciled (0 migration(s), 0 column(s))
done: 2 tenant(s), 0 failed

The new customer goes from 0 to 79 tables, the existing one does not move. This is the command to run as the last step of every deploy: no customer can then fall behind the code.

The data does not mix

titles of the new customer : 0
titles of the first one : 8

This is not a filter someone could forget: these are two databases.

Suspending is not deleting

Fenêtre de terminal
kewos tenant drop library2 --master-url ...
suspended tenant 'library2'

The word is misleading and the behaviour is the right one: drop suspends. The registry row stays, its status flips to suspended, and the database is untouched (its tables and data are still there, verified). A suspended customer serves no requests, but comes back whole:

Fenêtre de terminal
kewos tenant restore library2 --master-url ...

What the server sees

Every HTTP request carries its customer (subdomain or header), a middleware resolves it in the registry and opens that customer’s connection. No business code opens a connection itself; that is the project’s rule 14, and it is what makes the isolation structural rather than disciplined.