Platform · Stack & Engineering Standards
A boring, typed, pinned stack for a platform that has to last
One3 is designed as a TypeScript modular monolith on PostgreSQL, with Python reserved for AI services, durable workflows on Temporal, and every version and licence pinned and checked.
The principles behind the stack
The stack is chosen for a platform that has to carry many apps on one kernel. A few rules shape every choice:
- TypeScript-first product code. The kernel, the Action Bus, all Packs, the API, workers that touch business objects, the realtime gateway, web and mobile are TypeScript. One language for the product surface means shared contracts, shared types and one hiring profile.
- Python only for AI and ML. Agent runtime, retrieval, evals, fine-tuning, embeddings and model serving run in Python. Python services never own business writes. They call the Action Bus like any other actor.
- Contracts are generated, never hand-copied. zod schemas become JSON Schema, then OpenAPI, then a TypeScript client and Pydantic models. A contract change is one pull request that regenerates everything, and CI fails on drift.
- Boring over novel on the hot path. Pre-1.0 libraries are allowed only off the hot path, or with an explicit spike and exit plan.
- Managed services inside a complexity budget. Production in W0–W1 runs at most six core infrastructure systems.
The stack in plan numbers
- core infrastructure systems allowed in production in W0–W1
- 6
- open spikes and decisions mapped to sprints S0–S3
- 16
- stack layers with written decision tables
- 14
- planned interface languages in W2
- 8
The stack by layer
| Layer | Planned choice | Notes |
|---|---|---|
| Runtime and monorepo | Node.js 24 LTS, pnpm, Turborepo, uv workspaces for Python | TypeScript 7 for type-checking, SWC for builds, Biome for lint and format, Vitest and Playwright for tests |
| Core API | NestJS 12 on the Fastify 5 adapter, as a modular monolith | zod 4 validation via Nest's native Standard Schema support; OpenAPI generated from the same schemas; Scalar for the API reference |
| Database | PostgreSQL 18, managed in an India region, with point-in-time recovery | Row-level security for tenancy; pgvector, pg_partman, pg_trgm and btree_gist extensions |
| Data access | Drizzle ORM and drizzle-kit migrations, node-postgres, PgBouncer in transaction mode | Drizzle v1 behind an S0 go/no-go spike, with a stable fallback line |
| Cache | Valkey 9 | Redis-protocol compatible under a BSD licence |
| Identity and access | Keycloak or a managed IdP (by ADR); OpenFGA for relationship-based authorisation | OIDC, SAML and organisations; the same authorisation checks for people and agents |
| Workflows and events | Temporal (Cloud in Mumbai or self-hosted, by ADR); NATS JetStream | Temporal for anything durable or human-in-the-loop; NATS for event fan-out; no third job system in W0–W2 |
| Realtime | A separate WebSocket gateway on NestJS and Fastify; Yjs and Hocuspocus; LiveKit from W2 | Collaboration for docs and wiki; audio, video and voice agents |
| Web | Next.js 16 and React 19.3, Tailwind CSS 4, Radix UI and shadcn/ui, TanStack Query, Table and Virtual | TipTap for rich text, Univer for sheets, Apache ECharts for charts, MapLibre for maps, next-intl for Indian languages |
| Mobile | Expo SDK 57 (React Native), Expo Router, expo-sqlite | Offline sync engine decided by a spike before the W2 mobile build |
| AI services | Python 3.13, FastAPI, Pydantic v2, Pydantic AI on Temporal workers | LiteLLM model gateway, Langfuse tracing, Presidio for PII, promptfoo and DeepEval for evals |
| Observability | OpenTelemetry, Grafana Alloy, Grafana Cloud or self-hosted (by ADR), Langfuse, Sentry SaaS | Internal-use observability tools are never exposed to tenants |
| Security tooling | Semgrep with custom One3 rules, osv-scanner, Trivy, gitleaks, cosign | Images signed and verified at deploy; SBOMs produced |
| Infrastructure | Docker Compose in W0–W1, then managed Kubernetes or k3s from W2 by ADR; Helm 4; OpenTofu; Ansible | GitHub Actions for CI; Argo CD for GitOps from W2 |
Service topology: a modular monolith with justified services
Most of One3 is planned to run as modules inside one core service. A module becomes its own service only when it has a different scaling profile, runtime, availability need or security boundary.
- 1
Edge
Cloudflare for DNS, WAF and Tunnel, then a Traefik API gateway.
- 2
Core
The NestJS-on-Fastify modular monolith holds the kernel and all TypeScript Packs, reading and writing Postgres through Drizzle, with Valkey alongside.
- 3
Events
An outbox relay publishes changes from Postgres to NATS JetStream, which feeds TypeScript Temporal workers, the indexer and the AI runtime.
- 4
AI runtime
Python services run agents, retrieval and evals, and call models through a LiteLLM-based gateway with a One3 router to local or frontier models.
- 5
Realtime and MCP
A separate WebSocket gateway and an MCP gateway sit beside the core.
- 6
Media workers
FFmpeg, text-to-speech and speech recognition run as separate workers writing to object storage.
The complexity budget
In W0–W1, production is planned to run at most six core infrastructure systems: PostgreSQL (with pgvector and PgBouncer), Valkey, Temporal, NATS JetStream, identity, and observability. Libraries do not count. Any new stateful server needs an admission checklist first: owner, backup and restore test, upgrade plan, runbook, cost and licence. ClickHouse, Cube, OpenSearch and Qdrant are deferred to W3 unless measured need appears, and a graph database is evaluated in W4.
Backend engineering standards
The plan sets written standards for the NestJS and Drizzle layers so many teams and agents can build modules the same way.
One command pipeline
The Action Bus is One3's own command pipeline. A second command or event bus is not adopted, so policy, audit and idempotency stay on one path.
Tenancy in the database
Row-level security is declared in the schema. A tenant-context transaction helper is designed to work safely behind PgBouncer transaction pooling.
Machine-readable errors
A single error model with machine-readable error codes across the API.
Idempotency and versioning
Written rules for idempotency keys and API versioning on every endpoint.
Fastify-native plumbing
No Express middleware. Logging uses Pino through Fastify's built-in logger, with tracing through OpenTelemetry.
Real dependencies in tests
Testcontainers run real Postgres, Valkey, NATS and Temporal, because row-level security, pooling and migrations cannot be mocked.
AI services in Python
The AI side follows the same contracts and the same durability model as the TypeScript core.
Typed agents on durable workflows
Pydantic AI is the primary agent framework, running on Temporal Python workers so agent runs survive restarts.
Read-mostly data access
SQLAlchemy Core with asyncpg, scoped by row-level security. Business writes always go through the Action Bus.
Hardened model gateway
LiteLLM runs from One3's own built image, pinned by hash, with a minimum release age before any upgrade.
Lab serving and fine-tuning
vLLM, llama.cpp and TEI for serving in the lab; Unsloth core with TRL for fine-tuning; MLflow as the registry.
Evals and PII
promptfoo and DeepEval in CI, with Presidio redaction tuned for Indian identifiers such as PAN, GSTIN and IFSC.
Version pinning and upgrade policy
| Artefact | Rule |
|---|---|
| npm dependencies | Exact versions only, with pnpm catalogs so the monorepo uses one NestJS, one React and one zod |
| Python | uv.lock committed with hashes |
| Containers | Base images pinned by digest and rebuilt weekly |
| GitHub Actions | Pinned to a full commit SHA |
| Updates | Renovate opens grouped pull requests after a minimum release age: 3 days by default, 7 days for AI libraries, security scanners and anything with install scripts |
| Major versions | A time-boxed spike, then an ADR, then a migration pull request; runtime dependencies are never auto-merged |
Why pinning is strict
The plan cites a real supply-chain incident: in March 2026 a security scanner's release pipeline and then releases of a popular LLM gateway package were compromised through CI credentials. That is why versions are exact, images are pinned by digest, actions are pinned by SHA, and AI libraries wait seven days before an upgrade.
Licences are part of the stack
Every component carries a licence check. MIT, BSD, ISC, Apache-2.0, PostgreSQL, unmodified MPL-2.0, 0BSD and CC0 are allowed without review. AGPL, GPL, LGPL in shipped code, and source-available licences need legal review before they are embedded or offered as a service.
A few AGPL tools are used internally and unmodified only, such as the observability stack and load-testing tools. They are never redistributed or exposed to tenants as a feature. Every licence is a Fact Register row and is re-checked on major upgrades. See the Open-Source Foundations page for the full engine rules.
Deployment by stage
| Stage | Where | Purpose |
|---|---|---|
| S0 | A build and execution machine running Docker Compose with all services and local models, with a cloud fallback for every machine-dependent task | Development, CI, staging, AI Lab, internal use |
| S1 | Build machine plus a small cloud production setup in an India region with managed Postgres | Design partners with real data |
| S2 | Cloud Kubernetes with one production cell in India and disaster recovery in a second region | General availability and first tenants |
| S3 | Multiple cells (India, EU/US) and silo cells for enterprise | Scale and enterprise |
| S4 | Adds the One3 Box on-premises appliance and edge nodes | Sovereign and offline use |
Questions from technical buyers
Is One3 a set of microservices?
No. It is planned as a modular monolith with a small number of justified services. A module is split out only for a different scaling profile, runtime, availability need or security boundary.
Where will my data be hosted?
Production is planned in an India region by default, with managed PostgreSQL and point-in-time recovery. Multi-region cells and silo cells for enterprise come in later stages.
Can the Python AI services change my records directly?
No. Python services never own business writes. They call the Action Bus like any other actor, so the same policy, approval and audit rules apply.
Which versions are fixed today?
The plan records a baseline verified on 2026-09-15, such as Node.js 24 LTS, PostgreSQL 18, NestJS 12, Next.js 16 and Python 3.13. Versions move often, so Renovate keeps them current under the pinning rules.
Is there a mobile app?
Mobile is planned on Expo (React Native) from W2. The offline sync engine is still an open decision, settled by a spike and an ADR before the W2 mobile build.
Which decisions are still open?
The plan lists 16 spikes for sprints S0–S3, including the Drizzle v1 go/no-go, the managed Postgres provider in India, identity and Temporal hosting, observability hosting and the agent framework bake-off.
Review the stack with our team
Talk to us about One3's architecture, hosting, security tooling and engineering standards.