Multi-tenancy
Multi-tenant by construction, not by convention.
Multi-tenancy is the thing most backends get wrong quietly. Aaly applies tenant scoping below the API, on every endpoint, so there is no isolation rule for a person or an agent to forget on a new route.
Why this fails quietly
On a conventional backend, isolation is something you remember to do. A filter in a query, a policy on a table, a check before a write. Each one is correct until the day one of them is missing, and a missing one does not fail loudly. The table works, the app works, the tests pass. The only signal is a customer reading another customer's data.
That is survivable when a human adds a table every few weeks and reviews the migration. It is much less survivable when an agent adds one on request, several times a day. Creating the table is one call. Enabling isolation and writing a correct rule against the right claim is a second thing that has to not be skipped, and skipping it looks exactly like success.
What Aaly does instead
Tenancy is a property of the project, not a rule you attach to each table. This is the entire configuration:
{ "project": "helpdesk", "multiTenant": true, "publicSignup": true }From there, every record belongs to a tenant and every request is answered within one. The same request under two customers' tokens:
Tenant A's tokenGET /orders 200 tenant A's ordersGET /orders/ORD-9f21 200 belongs to tenant ATenant B's tokenGET /orders 200 tenant B's ordersGET /orders/ORD-9f21 403 not your record
There is no query you can write that returns another tenant's row, because you do not write the query. Aaly serves the API from your definition, so the isolation lives in the layer answering the request, not in code you own and have to keep correct.
Why there is no policy to get wrong
Aaly generates no backend code. Your agent writes a definition: entities, fields, relationships, rules. Aaly serves the API from it. There is no controller to review, no auth middleware to audit, and no tenant filter that a model may or may not have remembered on this particular run. The most reliable backend code is the code nobody writes.
This is also why a schema change stays cheap. Add a field and the contract updates; every client keeps working, because there is no generated backend in anyone's repository to fall out of sync with it. The cost of the tenth change looks like the cost of the first.
Check the backend you have now
If you are on Postgres or Supabase today, isolation depends on row-level security being switched on for each table and a policy being written against it. Both steps are per table, and a table that missed them answers to anyone holding the anon key.
Paste your schema and see which tables are exposed → It runs entirely in your browser. Nothing is uploaded.
The full Supabase comparison, including where Supabase is the better choice →
Multi-tenancy is on in every project, on every plan.
Plans differ in how many tenants they carry, never in whether isolation applies. The free tier includes 4.
Start building free