ADR 0002: Locked Stack — FastAPI + React + Postgres¶
Status: Accepted Date: 2026-04-29
Context¶
A new app is created from the template-app/ either by a human or by an AI agent. Allowing stack choices at creation time creates two problems:
- Agent reliability collapses when there are multiple paths. Each combination (Vue+FastAPI, React+Django, etc.) is a different surface for the agent to get wrong.
- Shared packages multiply. A
packages/auth-clientfor every language/framework combination quickly becomes unmaintainable for a small team.
Decision¶
Every new app uses exactly one stack:
- Frontend: React 18 + TypeScript + Vite + Tailwind.
- Backend: Python 3.12 + FastAPI + SQLAlchemy 2.x + Alembic.
- Database: Postgres 16, one database per app.
The template app and the scaffold script enforce this. Agents are explicitly told not to swap parts of the stack.
Consequences¶
Positive:
- One template to maintain, one set of SDKs, one set of conventions.
- Agents have a single path to follow — much higher success rate.
- Onboarding (human or AI) is identical for every app.
- Shared code (packages/auth-client-py, packages/ui) actually gets reused.
Negative:
- Apps with genuine reasons to use a different stack (a Go service that needs raw performance, a data-science app that wants Streamlit) can't use the template.
- This is acceptable — those edge cases can live as one-off services in services/ with bespoke setup, and we'd build a second template later if a pattern emerges.
Notes for future evolution¶
If a second stack is ever needed, the right move is a second template (template-app-go, template-app-streamlit) — not making the existing template configurable. The agent then reads the right AGENT_INSTRUCTIONS.md for whichever template the user picks.