Skip to main content

2.2 Provision tenant

Outcome

A new tenant DB exists on a chosen db_server, all tenant migrations applied, and a row exists in identity.tenant with status active.

Prerequisites

What "provisioning" actually does

Steps

  1. Run the provisioning CLI

    pnpm tsx scripts/provision-tenant.ts \
    --slug acme \
    --name "Acme Behavioral Health" \
    --region eastus2 \
    --vertical behavioral \
    --states OH,IN \
    --tier standard \
    --requested-by "you@medsuite.com"

    The CLI:

    1. Picks the least-loaded db_server for the region.
    2. Creates the tenant DB and the app-tier role.
    3. Runs all packages/database/src/migrations/tenant/* migrations on the tenant DB.
    4. Inserts identity.tenant (status='active').
    5. Stores the new app-tier password in Key Vault under rcm_tenant_<slug>_app_password.
    6. Writes a TENANT_PROVISIONED audit row.
    7. Prints the resulting tenant_id and a smoke-summary.
  2. Verify in the Admin UI

    Admin → Tenants should now show Acme Behavioral Health with status active.

  3. Spot-check the tenant DB

    TENANT_DB_PASS=$(az keyvault secret show \
    --vault-name kv-rcm-prod-eastus2 \
    --name rcm_tenant_acme_app_password --query value -o tsv)

    psql "host=pg-rcm-tenant-eastus2-01.postgres.database.azure.com \
    user=rcm_tenant_acme_app dbname=rcm_tenant_acme sslmode=require password=$TENANT_DB_PASS" \
    -c "SELECT count(*) FROM information_schema.tables WHERE table_schema NOT IN ('pg_catalog','information_schema');"

    You should see ~100 tables (this is the tenant schema baseline).

Slug naming rules

  • Lowercase letters, digits, and hyphens only.
  • 3–32 characters.
  • Reserved slugs are blocked: admin, api, app, ops, www, static, docs, master, platform, health.

What's NOT done yet

After this step the tenant is provisioned but has zero users, zero org structure, no ingestion feeds, no payer config. That's 2.5–2.10.

Validation

CheckExpected
identity.tenant WHERE slug='acme'1 row, status='active'
identity.tenant_audit WHERE event_type='TENANT_PROVISIONED'1 row matching the slug
Tenant DB existspsql connect succeeds
Migrations appliedknex_migrations count matches Phase 1 master baseline

Troubleshooting

SymptomLikely causeFix
CLI: "no eligible db_server"All db_server rows in the region are at capacityAdd a new db_server row + provision a new flexible server (see Phase 1.2).
Migration X fails partwayTenant DB partially createdThe CLI is idempotent — rerun. If still failing, drop the half-created DB and rerun.
Slug rejectedReserved or duplicatedPick a different slug.

Next

2.3 — Subdomain and TLS