003: Designing A Backend For A One Person AI Company
TL;DR: Solo Founder Backend Architecture in 60 Seconds
- One droplet, one Postgres server, multiple databases. Owned end to end, $18 per month, no SaaS that can surprise bill you.
- One database per product, plus a shared hub for cross product analysis. Schemas alone do not survive multi product growth. The split has to be at the database level.
- Firewall PII from the LLM context with a dedicated Postgres role.
mcp_roreads from a warehouse schema only, denied on PII columns. The MCP never touches raw product data. - Defer with a trigger, not with a vibe. Every deferred decision lands on a scaling backlog with a trigger, an action, a cost, and an effort estimate.
- Publish the cost ceiling, not just the cost. A table that caps every category by tier kills the open ended bill that drove the migration in the first place.
Solo founder backend architecture is the leverage point most builders skip until the bill scares them into rebuilding the wrong thing. This episode plans the entire backend that will sit under everything I ship: the Hero's Journey app, the consulting business, christianstrunk.com analytics, and the newsletter. One droplet, one Postgres server, multiple databases, a dedicated Postgres role for the Claude Code MCP, and a 28 item scaling backlog. The work was not picking the stack. The work was getting the shape right around the stack so future me cannot blow it up. This article extracts the principles. The session is the case study.
Why this matters
I am leaving Make.com, Airtable, and n8n. Not to save twenty dollars. The migration is about who owns the system when the bill jumps or the vendor changes their terms. After fifteen years in product management at companies like SumUp and Trade Republic, and a parallel career as a trained body psychotherapist, the pattern I see in every solo founder I coach is the same: the early tooling choices that felt frictionless become the late stage choices that cap your business. The right time to plan the backend is before the data starts flowing. The right shape is small, owned, and designed against the actual business, not a tutorial app. Use these principles in your version.
#1: Plan the backend against the whole business, not just the app
The mistake I see most often when a founder briefs an engineer is scoping the conversation to one product. The brief sounds like "I am building an app and need a database for it." The result is a database that fits one product, a tooling choice that fits one product, and a cost shape that fits one product. Three months later a second product or a marketing analytics need lands on the same box and the architecture has to be redone.
In this session the brief was the opposite. The hub of the business (christianstrunk.com, Google Search Console, GA4, Microsoft Clarity, the newsletter, the consulting CRM, the financials) sits next to the first product (the Hero's Journey app) and any product that follows it. The architecture has to hold all of it without coupling it. The shape that survives that pressure is one Postgres server with one database per product and one shared database for the business, cross referenced at read time through a warehouse schema, never through cross product queries.
The portable rule: when you brief the architecture, brief the whole business. The product is a tenant of the system, not the system itself.
#2: One database per product, with a warehouse for cross cutting analysis
The cleanest sounding default is one database with a schema per product. It is simpler to back up, simpler to reason about, simpler to query. For the first three months it is also correct. After that it stops being correct.
The reasons are operational, not regulatory. GDPR was the trigger that surfaced the question in this session, but Claude's pushback was right: GDPR is not the reason on its own. The reasons are blast radius (one bad migration takes everything down), differing workload profiles (the app writes hot, the warehouse reads cold), different security surfaces (the app touches end user PII, the hub does not), independent deployability (touching the app database should not block a marketing analytics deploy), and the clean exit story (selling a product means dumping a database, not extracting rows from a shared one).
| Decision | Picked | Rejected | Why |
|---|---|---|---|
| Database layout | One server, one DB per product, shared hub for business | One DB with schemas only | Blast radius, independent deploys, clean exit per product |
| Cross product analysis | Nightly ETL into hub.warehouse (pseudonymized) | Direct cross DB joins | Keeps raw product DBs untouched, gives MCP a safe surface |
| ORM | Drizzle | Prisma | TypeScript ergonomics, current mindshare, lighter footprint |
| Queue | pg-boss on Postgres | Redis | One fewer service, transactional with the data it operates on |
The warehouse schema is where Claude Code's MCP reads from. The raw product databases never get a read role assigned to the MCP. Cross product questions ("which newsletter subscribers also signed up for the app this month?") get answered against pseudonymized aggregates in the warehouse, not against joined PII.
The portable rule: split databases by write boundary, unify at read time through a warehouse. Schemas alone do not survive a second product.
#3: Firewall PII from the LLM context at the database role layer
The convenience of MCP is also the risk. The moment Claude Code can query Postgres, it can also accidentally surface PII into a transcript, into a screenshot, into a future training set. The fix is not to police prompts. The fix is at the database role.
In this architecture the MCP authenticates as mcp_ro. The role has read access to one schema (hub.warehouse) and explicit DENY on every column tagged PII. There are four other roles, each with the minimum surface their workload requires: hub_rw writes to the business schemas, app_rw writes to the Hero's Journey app database, warehouse_writer runs the nightly ETL, backup_ro reads everything for pg_dump. None of them have admin. Postgres enforces the boundary; the application code cannot loosen it.
In my coaching experience, the founders who get into trouble with AI assistants are not the ones who ignored security. They are the ones who built the boundary at the application layer, where a single bug or a single prompt can step over it. The boundary belongs in the layer below the one being prompted. Postgres roles are that layer for data, the way firewall rules are that layer for the network.
The portable rule: every LLM connection to your data goes through a role that the database itself enforces. If a prompt cannot loosen the boundary, the boundary holds.
#4: Defer with a trigger, not with a vibe
Every architecture session produces a list of "we will do that later." Most of those lists are useless within a month because "later" is a feeling, not a condition. The list rots, the team forgets, and the deferred items either silently become tech debt or get done at the wrong time under pressure.
This session produced a 28 item scaling backlog instead. Every item has four fields: trigger (the measurable condition that fires it), action (the concrete change), cost (rough monthly delta), effort (rough hours). Six tiers, from S1 (first real user) to S6 (acquisition or wind down). The backlog also has an explicit "never do this" section to kill the recurring temptations (Kubernetes, microservices, separate vector database, hosted Sentry).
| Tier | Trigger | Picked action | Cost delta | Effort |
|---|---|---|---|---|
| S1 | First real user signs up | Replace ops.errors table with self hosted GlitchTip on the same droplet | $0 | 4h |
| S2 | Postgres CPU > 60% sustained | Add managed Postgres alongside, migrate hub first | +$15/mo | 6h |
| S3 | App responses > 300ms p95 | Add a read replica for the analytics dashboard | +$15/mo | 4h |
| S4 | Spaces > 100GB | Move cold backups to Backblaze B2 | -$3/mo | 2h |
The backlog is also where Sentry landed. Hosted Sentry was rejected because the free tier caps at 5.000 errors per month with silent drops past the cap, and the typical solo team hits the paid tier within three to six months. GlitchTip is the drop in replacement, deferred until the first real user lands, captured as item S1.
The portable rule: every "not now" decision needs a trigger, an action, a cost, and an effort. The version without the trigger gets either done too early or never.
#5: Publish the cost ceiling, not just the current cost
The reason I am leaving Make.com is not that the current bill is $35 per month. The reason is that the current bill could become $200 next quarter and I would not see the change coming until the invoice landed. A surprise bill is a vendor strategy, not an accident.
The fix is to publish the cost ceiling per tier, not just the current cost. The architecture document carries a cost table with four rows: MVP (~$25/mo), MVP with GlitchTip (~$25/mo, fits in 4GB), MVP with managed Postgres (~$40/mo), MVP with read replica (~$55/mo). No category can surprise bill above the published ceiling because every category is either a fixed price line item (the droplet, the snapshots, Cloudflare free tier) or an upgrade that fires from a known trigger on the scaling backlog.
In my coaching experience, founders almost never plan for cost ceilings because the early bill is small enough to ignore. The ones who later get squeezed are not careless. They never put the ceiling on paper, so there was nothing to defend against when the SaaS vendor changed pricing tiers or the data volume drifted. A published ceiling is also a kill switch. If a tier exceeds it, you have a written rule that says "stop, reroute, escalate."
The portable rule: write the cost ceiling per tier before the first dollar moves. The number you write is the number you can defend.
#6: Get a human review before the code lands, even when AI did the planning
The session ended with one prompt that I almost did not write. I asked Claude to compress the 90 minutes of decisions into a WhatsApp message I could send to an engineering friend who has built backends for unicorns. Two paragraphs, every consequential decision, every rejected alternative, the ceiling. He gets it on the train, reads it in five minutes, and either green lights Phase 1 or pushes back before code lands.
The point is not that AI cannot plan a backend. The point is that the cost of a human review at this stage is fifteen minutes of someone's day and the cost of skipping it is weeks of unwinding bad foundations. If you have ever had to walk back a database schema after the first production write, you already know the math. If you are mid migration to AI assisted planning, the highest leverage habit you can add is a one paragraph summary sent to one person who has done this before. AI plans, human signs off, then the build phase begins. This is the kind of architecture sparring I bring to my product coaching engagements when the founder needs a second pair of eyes before code lands.
The portable rule: the architecture is not locked until a human who has shipped one like it has read it and said "go."
What is next
Episode 004 is Phase 1 of the build: provision the droplet, set up Docker Compose, Postgres with the role layout, Caddy reverse proxy, the backup pipeline, and the first sign of life on api.christianstrunk.com. No real data touches the system until the backup and restore drill works. That sequencing is the lesson from this session repeated: the part that protects what you build comes before the part that builds it. The previous episode, planning a gaming app with user story mapping, is where the product side started. This episode is where the infrastructure side starts. Both feed into the same system. Subscribe so episode 004 lands when the foundations are live.
All prompts I used in this session
#1 Prompt
Act as a senior backend engineer with a brilliant eye for detail and the background of having built many scaling backends for companies and rockstar solopreneurs. In this project I'm planning to build this app which will collect data, tracking, event payments and much more. At the same time I have as a hub my website christianstrunk.com which also collects data, we have Google Search Console, Bing Webmasters, GA4, Microsoft Clarity. Then I have my business operations, and consulting business which generates money and I have fix costs (personal costs) and I would like to also map out later my financials. And then I have my newsletter which also links to all the mentioned channels, the newsletter itself has data, numbers, conversions, etc. My goal is to go away from n8n and make.com as well as Airtable and put everything on one DigitalOcean droplet and let it run there. I have no idea how to do it and need your technical advice and feedback. Ultrathink, let's map this out step by step.