Skip to content

CortexBuild — Tech Stack Decision Log (v0.1)

For each decision: what we picked, why, what we considered, when to revisit.

Backend

Component Pick Why Considered Revisit
Language Python 3.12 Mature LLM ecosystem; FastAPI is excellent; team familiarity Go (binary distribution), TypeScript (single-language), Rust (perf) If performance becomes bottleneck (unlikely v1)
Web framework FastAPI Async; OpenAPI auto-gen; WebSocket native; Pydantic Litestar (newer), Django (too heavy), Flask (sync only) v2 if FastAPI ecosystem stalls
ORM SQLAlchemy 2.0 (async) Industry standard; well-supported SQLModel (good but young), raw asyncpg (too low-level) Stick
Validation Pydantic v2 Bundled with FastAPI; fastest in class attrs (older), msgspec (faster but younger) Stick
Migrations Alembic Mature; SQLAlchemy-native Skema (younger), raw SQL Stick
Background jobs Postgres LISTEN/NOTIFY (v0) → Temporal (v2+) LISTEN/NOTIFY is free + good enough for v0; Temporal is correct for long-running multi-step workflows Celery (too painful), Dramatiq (decent), Hatchet (interesting), Inngest (closed cloud) v2: adopt Temporal when task graphs exceed 10 steps
WebSocket FastAPI native Sufficient; no separate process Socket.io (overkill), Centrifugo (overkill) Stick

Frontend

Component Pick Why Considered Revisit
Framework Next.js 15 (App Router) Mature, opinionated, great DX, easy hiring Remix (good but smaller community), SvelteKit (smaller hiring pool), Phoenix LiveView (different paradigm; would limit team) Stick
Styling Tailwind CSS v4 Standard CSS modules (too verbose), Emotion (slowing) Stick
Component library shadcn/ui Copy-paste, full control, no lock-in Mantine (heavier), Radix raw (too low-level) Stick
State Zustand + TanStack Query Light + powerful Jotai (similar), Redux (too heavy), MobX (declining) Stick
Real-time Custom WebSocket + TanStack Query invalidation Simple, debuggable Pusher (vendor lock), Ably (vendor lock), Liveblocks (overkill) Stick
Forms React Hook Form + Zod Best-in-class Formik (declining), Conform (too new) Stick

Data

Component Pick Why Considered Revisit
Primary DB Postgres 16 Boring; jsonb; full-text; pgvector available MongoDB (wrong shape), CockroachDB (overkill), MySQL (worse jsonb) Stick forever
Cache / queue broker Redis 7 Standard KeyDB (declining), DragonflyDB (interesting; revisit v2) v2: consider DragonflyDB
Search Postgres FTS (v0) → Meilisearch (v2+ if needed) FTS is sufficient for project-internal search Elasticsearch (operational nightmare), Typesense (good alt) When projects > 1M rows of searchable content
Object storage S3 (or compatible) Standard GCS (fine), Azure Blob (if Azure-deployed) Stick
Audit log archival S3 + Athena for old logs Cheap cold storage; SQL-queryable DynamoDB (too pricey for write-heavy), CloudWatch (vendor-only) Stick
Embeddings pgvector (on Postgres) One DB; no separate service Pinecone (vendor lock), Qdrant (decent), Weaviate (heavy) If pgvector latency degrades at scale; revisit at 10M vectors

Execution

Component Pick Why Considered Revisit
Dev VM substrate Daytona (v0/v1) → custom Firecracker (v3+) (planned, Phase 1) Daytona is OSS, devcontainer-native, fast E2B (SDK-first, fits short tasks), Modal (stateless-focus, wrong fit), Codespaces (lock-in, slow), Coder (good but smaller) v3: custom Firecracker for cost & control at scale
Sandboxing Docker (inside Daytona) Standard gVisor (overkill), Kata (overkill) Stick
Network policy Custom iptables in workspace base image Restrict egress Cilium (k8s only) v2: consider eBPF if compliance demands

LLM integration

Component Pick Why Considered Revisit
Provider abstraction Custom thin interface No churn from frameworks LangChain (changes weekly), LlamaIndex (heavy), CrewAI (rapidly changing), Llama Stack (interesting; revisit v2), Vercel AI SDK (frontend-focus) Stick; consider AI SDK adapters at v2
Token counting tiktoken (OpenAI) + anthropic SDK count_tokens Provider-native Generic estimators (inaccurate) Stick
Caching Redis (prompt hash → response) Simple LangChain cache (too coupled) v2: consider Anthropic prompt caching natively
Observability OpenTelemetryHoneycomb (v0/v1) → Langfuse (v2+) OTel is standard; Honeycomb best for debugging; Langfuse purpose-built for LLM Helicone (good cloud-only), Phoenix (great OSS) v2: add Langfuse alongside OTel

Auth

Component Pick Why Considered Revisit
Identity Clerk (v0/v1) → custom (v2+) Clerk for speed; expensive at scale WorkOS (better for enterprise), Supabase Auth (decent), Auth0 (expensive), Ory (OSS but heavy), Better Auth (interesting) v2: when monthly Clerk bill > $2k OR enterprise customers demand SSO customisation
SSO WorkOS (v2+) Enterprise SSO standard Clerk's enterprise tier, Auth0 When first enterprise customer asks
Authorization Custom + Casbin Fine-grained policies; project-scoped roles Cerbos (great but separate service), OPA (overkill) Stick
Secrets at rest AWS KMS (or equivalent on chosen cloud) Standard HashiCorp Vault (operational cost) Stick

CI / CD (for CortexBuild itself)

Component Pick Why
CI GitHub Actions Standard
Container registry GitHub Container Registry Same ecosystem
Image scanning Trivy + Grype Best OSS scanners
Secrets in CI GitHub Actions secrets + OIDC to cloud No long-lived keys
Deploy Fly.io (v0/v1) → AWS ECS (v2+) → AWS EKS (v3+) Fly is best DX for early; ECS is sufficient for v2; EKS only when needed

Telemetry / Observability

Component Pick Why
Metrics OpenTelemetryHoneycomb OTel for instrumentation; Honeycomb for query
Logs structlog (Python)Honeycomb Structured by default
Traces OpenTelemetryHoneycomb Single pane
Error tracking Sentry Standard
Uptime Better Stack Cheap, good DX
LLM-specific Langfuse (v2+) Cost + quality dashboards per agent

Payments

Component Pick Why
Billing Stripe Standard
Usage metering Custom (write to audit_log) Simple; tied to our domain model
Invoicing Stripe Invoicing Standard

Developer tooling (for our own team)

Component Pick
IDE VS Code / Cursor (whatever team prefers)
Repo platform GitHub
Project mgmt Linear
Docs Markdown in repo + Notion for non-engineering
Chat Slack
Design Figma

What we explicitly avoid

  • LangChain / LlamaIndex / CrewAI as orchestrator core — API churn breaks everything
  • No-code orchestration tools (n8n, Zapier) — too opaque to debug
  • Microservices on Day 1 — monolith until proven otherwise
  • Kubernetes on Day 1 — Fly.io / ECS until proven otherwise
  • Multi-cloud on Day 1 — pick one, master it
  • GraphQL — REST + OpenAPI is enough
  • Bespoke message bus — Postgres LISTEN/NOTIFY → Temporal is the path