Scaling
The same code runs solo/inbox and corp/eng/sre/oncall. Arizuko is multi-tenant by primitive: adding users is adding rows and folders, not deploying new infrastructure. The typical growth path is solo → dogfood → team → internet.
Multi-tenant by primitive
Every primitive — grants, routes, secrets, scheduled work — stores its state as rows. Adding a tenant means writing rows into those tables and creating a folder under groups/. The daemon graph stays fixed: one routd, one authd, one adapter per platform, N containers (one per active group). Ten users or ten thousand users, the architecture is the same.
Folder hierarchies have no fixed depth, and depth buys nothing. solo/inbox and corp/eng/sre/oncall get the same starting grants and run the identical code path; what either may do beyond the messaging floor is whatever was delegated to it. A solo user's chat and a support team's shared inbox run through the same routd, same runed, same container image.
The growth arc
Most deployments follow four stages. Each is a configuration change, not a rebuild.
| Stage | Shape | What changes |
|---|---|---|
| Solo | One folder, one channel, one user | Nothing — this is arizuko create |
| Dogfood | A handful of folders, trusted users | Add folders, issue invites, enable adapters |
| Team | A hierarchy under one world, shared admin | Folder tree, ACL rows, channel onboarding |
| Internet | Public-facing, untrusted callers | Route tokens, admission queue, egress sandbox |
The jump from solo to dogfood is a Slack bot token and a few invites. The jump from team to internet is a route token and tighter egress rules. No redeploy, no new containers, no schema migration.
Solo
arizuko create myagent
arizuko group myagent add tg:123456789 main
arizuko run myagent
One user, one channel. Getting started walks through the full setup.
Dogfood
arizuko invite myagent create --email alice@example.com
arizuko group myagent add slack:T1234/C5678 alice
Add adapters to .env, issue invites, create folders. See env reference for adapter tokens.
Team
arizuko group myagent add slack:T1234/C1111 eng
arizuko group myagent add slack:T1234/C2222 eng/frontend
arizuko acl myagent add alice@example.com "eng/**" "**"
Nesting a folder grants nothing on its own — the reach is whatever the glob says. eng/** covers eng and everything under it; a bare eng covers that one folder. See grants and scopes.
Internet
arizuko token myagent create --jid web:support
A route token lets anonymous visitors in. Add ONBOARDING_ADMISSION=queue to gate new users, and EGRESS_IMAGE=arizuko-egress:latest to put every spawn behind its own filtered proxy. See tokens and onboarding.
Where isolation comes from
Tenants share one store, one set of daemons, one container image. Isolation comes from three things:
- Folder containment. A group's agent runs in a container whose home is
groups/<folder>/. It cannot see sibling folders' files. Scopes explains the rules. - Grant resolution. Every MCP call checks
(caller, action, target)against the ACL. A folder holding only the default role cansendbut notregister_group. Grants explains the rows. - Egress filtering. Each spawn gets its own
egressproxy holding that folder’s allowlist, on a network with no other route out. It is instance-wide onceEGRESS_IMAGEis set, and the rules are per folder.
Cross-tenant read is structurally impossible: the container mount, the grant gate, and the egress proxy all bind to the folder. A bug in one group's skill doesn't leak into another group's context.
Capacity, not tenancy
Scaling arizuko is a capacity question, not an architecture one. One store handles thousands of groups; a single host runs hundreds of concurrent containers. When you hit the host ceiling, the answer is a second instance (a separate data directory, a separate systemd unit), not a rewrite. Each instance is fully independent — no shared state, no cross-instance routing.
This is intentional. The operational model is "many small instances" rather than "one distributed cluster." A support team runs one instance; a product team runs another; they share nothing but the binary. Operational blast radius stays small.