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 in SQLite rows. Adding a tenant means inserting 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. solo/inbox is a tier-1 folder (one slash). corp/eng/sre/oncall is tier-3 (three slashes). The tier number sets default grant permissions — deeper folders get tighter defaults — but the code path is identical. 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/**" "**"
Nested folders inherit from parents; ACL rows grant actions per 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, CRACKBOX_ENABLED=true to sandbox egress. See tokens and onboarding.
Where isolation comes from
Tenants share a single SQLite WAL file, a single set of daemons, a single 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 tier-2 agent cansendbut notregister_group. Grants explains the DSL. - Egress sandbox. Public-facing agents run through
crackbox, which limits outbound network to an allowlist. Sensitive deployments sandbox all tiers.
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. A single SQLite can handle thousands of groups; a single host can run 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.