Deployment and operations
The full click-by-click guide, with screenshots of each console, is planning/STRATL_DEPLOYMENT_GUIDE.html in the backend repository. This page is the engineer’s summary of the same deployment.
The shape
Section titled “The shape”| Part | Runs on | Address |
|---|---|---|
| API and PostgreSQL | Railway (one project: the api service from the backend repository, and a Postgres service) |
api.stratl.ai |
| Portal | Vercel (project from the web repository) | app.stratl.ai, forwarding /api to the API |
| Website | Vercel (project from the website repository) | stratl.ai |
| Docs | Vercel (project from the docs repository) | docs.stratl.ai |
| Custody | AWS: one S3 bucket and one KMS alias prefix per offered region, created by deploy/cloudformation/managed-custody.yaml; an IAM user with put, get and sign only |
per region |
| Resend, with a verified sending domain | notifications@stratl.ai |
The API on Railway
Section titled “The API on Railway”-
Create a Railway project with a PostgreSQL service; pick the region; turn on backups.
-
Add the
apiservice from the backend repository. The Dockerfile at the repository root builds it; migrations run at start; Railway waits for the health check (/healthz) before switching traffic. -
Variables (Raw Editor). Generate the secret with
openssl rand -base64 48.STRATL_ENV=productionSTRATL_DATABASE_URL=${{Postgres.DATABASE_URL}}STRATL_SECRET_KEY=<the openssl output>STRATL_CUSTODY_BACKEND=s3-kmsSTRATL_CUSTODY_REGIONS=in=ap-south-1:stratl-records-inAWS_ACCESS_KEY_ID=<from the CloudFormation stack>AWS_SECRET_ACCESS_KEY=<from the CloudFormation stack>STRATL_LOG_LEVEL=INFOPORT=8000RESEND_API_KEY=<from Resend>RESEND_FROM_EMAIL=notifications@stratl.aiRESEND_FROM_NAME=StratlSTRATL_PUBLIC_URL=https://api.stratl.aiANTHROPIC_API_KEY=<optional, for notice drafting>STRATL_ENV=productionturns on secure cookies and stops codes being shown on screen; the API refuses to start in production with the default secret key. Every setting. -
Before deploying, prove custody from your machine with the same AWS values:
uv run --directory api python scripts/check_custody.py. -
Deploy, read the logs, test on the temporary Railway address, then attach
api.stratl.ai.
The portal, website and docs on Vercel
Section titled “The portal, website and docs on Vercel”Three separate Vercel projects, one per repository, Node 22. The portal needs one variable, VITE_PUBLIC_API_URL=https://api.stratl.ai, which is only the address printed in the Get started snippets; its vercel.json rewrites /api/* to the API so the session cookie stays first-party, and sets no-store on those responses. The website and the docs need no variables. Attach app.stratl.ai, stratl.ai (with www redirecting) and docs.stratl.ai.
Custody on AWS
Section titled “Custody on AWS”Create the stack from deploy/cloudformation/managed-custody.yaml in each region you offer; after the first, pass its ApiUserName as ExistingApiUserName so one IAM user spans regions. Create an access key for that user. The template creates a versioned, encrypted, public-access-blocked bucket with Object Lock available, and one managed IAM policy per region that allows put, get and sign only (managed, not inline: IAM caps inline policies at 2048 bytes per user, which one region already fills). Custody.
Email with Resend
Section titled “Email with Resend”Add your domain, add the DMARC record Resend suggests so inboxes trust you, create an API key. Without a key the API logs codes instead of sending them, which is only acceptable locally.
Smoke test
Section titled “Smoke test”- Sign up at
app.stratl.ai/signup; the region list should show only the regions you configured. - Send a real record from your laptop with the SDK snippet on Get started.
- Walk the five steps of Get started to a verified bundle.
- On the Custody page the storage location should start with
s3://and the key card should say it is held in KMS. Redeploy the API and check the key id and chain head are unchanged. In the AWS console the bucket should hold a folder named after the workspace withrecords,checkpoints,artifactsandkeys.
Day to day
Section titled “Day to day”| You want to | Do |
|---|---|
| Ship a backend change | Push to main in the backend. Railway builds, runs migrations at start, waits for the health check |
| Ship a portal, website or docs change | Push to main in that repository. Vercel deploys; every pull request gets a preview |
| Change both API and portal in one feature | Two repositories, two pushes. Deploy the backend first so the UI never calls something the API lacks |
| Undo a bad deploy | Railway: Deployments → the last good one → Redeploy. Vercel: Instant Rollback. A backend rollback does not undo a migration |
| Update the offline verifier in the portal | make wasm-export in the backend, then commit and push the two files in the web repository |
| Update the API reference in the docs | make openapi in the backend, then commit and push in the docs repository |
| Read logs | Railway → api service → Deployments → View logs. Logs never contain content |
| Rotate the Resend key or the AWS access key | Change the variable in Railway; the service restarts. Never change STRATL_SECRET_KEY casually: it voids codes waiting to be used |