Technology Stack
Every technology choice is pinned to a specific version. This page documents what we use, why we chose it, and what we rejected.
Decision Matrix
| Component | Chosen | Rejected | Rationale |
|---|---|---|---|
| Monorepo tool | Nx | Turborepo, Bazel | Mixed Python+TS support; project graph; generators |
| JS package manager | pnpm | npm, yarn | Strict hoisting; disk efficiency; workspace protocol |
| Python package manager | uv | pip+venv, Poetry, PDM | 10–100× faster; lockfile; built-in venv |
| API Gateway | Go (chi) | Node/Express, Kong | Native concurrency; <5ms overhead; small binary |
| Content service | Python (FastAPI) | Go, Node | Best graph DB client ecosystem; AI library access |
| Auth provider | Clerk (SaaS) | Auth0, Cognito, custom | Weeks saved; handles MFA, social, magic links |
| Graph database | FalkorDB | Neo4j, ArangoDB | Redis-based (ops simplicity); Cypher compatible |
| Relational DB | PostgreSQL | MySQL, SQLite | Superior JSON support; pgvector; JSONB indexing |
| Search | Typesense | Elasticsearch, Algolia | Self-hosted; instant results; typo tolerance |
| Vector search | pgvector | Pinecone, Weaviate | No additional service; sufficient at <10M vectors |
| Container orchestration | Kubernetes (EKS) | ECS, Fly.io | Standard path to enterprise; ArgoCD native |
| IaC | Terraform | Pulumi, CDK | Most community modules; language-agnostic |
| GitOps | ArgoCD | Flux, Spinnaker | Declarative; UI; RBAC; easy rollback |
| Secrets | AWS Secrets Manager | Vault, Doppler | Native AWS integration; upgrade path to Vault |
| Observability | OpenTelemetry → Grafana | Datadog, New Relic | Open standard; vendor-neutral; free at scale |
| Error tracking | Sentry | Rollbar, Bugsnag | Best cross-platform SDK coverage |
| Mobile CI/CD | Expo EAS | Bitrise, Fastlane | Native Expo integration; no macOS runner needed |
| Resend | SendGrid, Postmark | Modern API; React Email templates; cost |
Node.js / TypeScript
| Technology | Version | Scope |
|---|---|---|
| Node.js | >=22 | Engine requirement |
| pnpm | 9.15.0 (exact) | Package manager |
| TypeScript | ^5.5 | All TS/JS — ES2022 target, strict, bundler resolution |
| React | ^19 | web, admin |
| React | ^18.3 | mobile (Expo 52 constraint) |
| React Native | ~0.76.0 | mobile |
| Next.js | ^15 | web, admin — App Router |
| Expo | ~52.0.0 | mobile — SDK 52 |
| Tailwind CSS | ^4 | web, admin (+ @tailwindcss/postcss v4) |
| Zod | ^3.23 | config — env schema validation |
| openapi-fetch | ^0.12 | sdk package (peer dep) |
| Vitest | latest | Testing (+ @vitest/coverage-v8) |
| Zustand | — | State management (all apps) |
| TanStack Query | — | Server state (all apps) |
Go
| Technology | Version | Scope |
|---|---|---|
| Go | 1.23 | gateway, auth, billing, notifications |
| Chi | v5.1.0 | HTTP router |
| Zerolog | v1.33.0 | Structured JSON logging |
Why Go for gateway/auth/billing/notifications? These services share traits: high-throughput routing decisions, webhook handling, persistent connections (APNs/FCM). Go's goroutine model, sub-millisecond startup, and ~10MB Docker images are worth the verbosity at these boundaries.
Python
| Technology | Version | Scope |
|---|---|---|
| Python | >=3.12 | content, ai, ingest |
| FastAPI | >=0.115 | content (8100), ai (8400) |
| Uvicorn | >=0.32 | ASGI server |
| Pydantic | >=2.9 | All Python services (extra="forbid") |
| pydantic-settings | >=2.6 | Config management |
| structlog | >=24.0 | Structured logging |
| Click | >=8.1 | ingest CLI framework |
| Anthropic SDK | >=0.39 | ai — primary LLM provider |
| OpenAI SDK | >=1.55 | ai — fallback LLM provider |
| pytest | >=8.0 | Testing (+ pytest-asyncio, pytest-cov) |
| Ruff | >=0.8 | Linting + formatting |
| mypy | >=1.13 | Type checking (strict) |
Why Python for content/ai/ingest? FalkorDB's Python client is the reference implementation. The AI ecosystem (Anthropic SDK, sentence-transformers, LangChain) is Python-native. Data transformation tasks are natural in Python.
Data Stores
| Store | Version/Image | Port | Purpose |
|---|---|---|---|
| FalkorDB | falkordb/falkordb:latest | 6379 | Primary graph DB — scripture content + relationships |
| PostgreSQL | pgvector/pgvector:pg16 | 5432 | Users, subscriptions, notes, AI embeddings |
| Redis | redis:7-alpine | 6380 | Cache, rate limiting, sessions, job queues |
| Typesense | typesense/typesense:26.0 | 8108 | Full-text + faceted search |
FalkorDB (port 6379) and Redis cache (port 6380) are separate instances. FalkorDB is a Redis-based graph database, but it is NOT the application cache. Never confuse them.
Version Pinning Policy
| Technology | Pinned Version | Upgrade Policy |
|---|---|---|
| Go | 1.23 | Minor releases quarterly |
| Python | 3.12 | Major annually |
| Node.js | 22 LTS | Even LTS annually |
| PostgreSQL | 16 | N-1 from latest |
| Redis | 7 | — |
| Expo SDK | 52 | Each Expo LTS |
| Next.js | 15 | — |
| Terraform | 1.9 | — |
| Kubernetes | 1.31 | Follow EKS supported versions |
Related Pages
- Architecture Overview — Why "language-right, not TypeScript-by-default"
- Monorepo & Tooling — Workspace structure and Nx configuration
- Data Architecture — Deep dives into each data store