Why Bones

Cloud

Everything production needs — servers, database, sites, files, email, AI, DNS, backups, and spending limits — in one AWS organization, defined as code in the repo.

The problem

A new app needs a dozen services before its first user signs up. Each one usually comes from a different vendor: one hosts the frontend, one runs the backend, one holds the database, and others send email, store files, serve DNS, and answer AI calls.

Every vendor is another account, another bill, another dashboard, and another set of terms. Your data ends up in five places, and nobody can say what the whole thing costs in a month.

What Bones does

Everything Bones runs lives in one AWS organization. It's one vendor, one bill, and one sign-in. Every piece is defined in infra/ as AWS CDK code, and every merge to main deploys it. See CI/CD.

JobServiceWhat it does for Bones
Run the backendEC2, or ECS on FargateRuns the backend/Dockerfile image. One server at the smallest size, containers when you grow
Hold the imageECRStores each backend image, tagged with the commit that built it
Store dataRDS for PostgreSQLYour users, organizations, and content, in a database you own
Store filesS3Uploads, avatars, blog bodies and media, terms, archived logs, and the built sites
Serve the sitesCloudFrontThe web app, marketing site, blog, docs, and API, each on its own hostname, with security headers
Names and HTTPSRoute 53, Certificate ManagerDNS for your domain, and one certificate for it and every subdomain, renewed on its own
Send emailSESVerification, password reset, and welcome mail from your own domain, with DKIM
Answer chatBedrockThe chatbot's model, called from your own account
Keep secretsSystems Manager Parameter Store, Secrets ManagerProduction's settings and the database password. Nothing secret sits in the repo or in GitHub
Keep backupsAWS Backup, KMSDaily database backups, copied to a locked vault in a separate account
Cap spendingBudgets, Cost ExplorerAlerts at $50, $120, and $150 a month, anomaly detection, and a cutoff at $150
Separate and sign inOrganizations, IAM Identity Center, IAMOne account per job, one sign-in across them, and guardrails no one can switch off from inside
Let CI deploy without keysIAM with GitHub's OIDCGitHub Actions gets short-lived credentials for one run, and stores none

Three things make it hold together:

  • One account per job. DNS and the sites, backups, and production each live in their own account. A mistake in one can't reach the others, and a backup survives the account it came from.
  • Guardrails above the accounts. Organization policies keep every account in approved regions and stop one from leaving the organization. They apply even to an administrator inside the account.
  • Local stand-ins, same API. On your machine, S3 is RustFS, SES is Mailpit, and Bedrock is Ollama. The code only talks to the standard API, so an environment variable picks which one answers. See AWS.

What it costs

The size of production is one setting in infra/app/environments.ts:

TierAboutRuns onGood for
Starter$33/monthOne server, one small databaseUp to about 1–3k monthly users
Growth$100/monthTwo containers behind a load balancerAbout 10–25k monthly users
High availability$275/monthUp to four containers, a standby database, a firewallAround 100k monthly users

That's the cost while idle. Email is $0.10 per 1,000, and the chatbot is about $0.0001 a message, capped at $10 a month across the app.

A tier that costs as much as the budget or more fails before it deploys, so moving up to High availability means raising the $150 cutoff first.

What isn't done yet

  • One environment. There's production and your machine. Staging is planned, not built.
  • One server on Starter. A deploy or a server failure means a short outage. Growth removes it.
  • No monitoring. Nothing alerts when the backend errors or slows down. Logs are archived to S3, not searched.
  • Email is in the SES sandbox until AWS grants production access, so it only reaches verified addresses.

Two services sit outside AWS on purpose. GitHub holds the code and runs CI/CD, and Google handles "Continue with Google" sign-in.

How it compares

OptionTrade-off
A vendor per job (Vercel, Neon, Resend, …)Each one is easy to start, but you manage every account, bill, and set of terms
An all-in-one platform (Supabase, Firebase)One vendor, but its own APIs, and leaving means rewriting the parts that use them
AWS set up by handOne vendor and standard APIs, but weeks of console work that no one can review or repeat

Bones is the third option with the setup already written. It's in the repo, reviewed in pull requests, and deployed the same way every time.

Go deeper

  • AWS — why one cloud, and what runs in production.
  • CI/CD — how a merge deploys.
  • infra/README.md — the stacks, first-time setup, and the full cost breakdown.