Disciplines · Conventions

Server frameworks & overlapping dependencies — sanctioned choices

The workspace currently ships four (fastify 114 packages, hono 67, express 19, NestJS 16).

3sections1 minread

On this page

Status: adopted 2026-07-16 (audit R-17, docs/audits/MONOREPO_ARCHITECTURE_AUDIT_2026-07-16.md). Enforcement is review-time until lint automation lands.

HTTP server frameworks#

The workspace currently ships four (fastify 114 packages, hono 67, express 19, NestJS 16). For new services:

Framework Status Use for
fastify ✅ sanctioned Platform/backend services (the majority pattern; @lilith/fastify-core exists)
hono ✅ sanctioned Edge runtimes, BFFs, lightweight gateways
express 🧊 frozen No new services. Existing 19 packages maintained in place; migrate opportunistically when a service is being rewritten anyway
NestJS 🧊 frozen No new services. The 16 existing packages are also the only reason emitDecoratorMetadata/experimentalDecorators are on in the global tsconfig (audit R-15)

HTTP clients#

Use native fetch via @oshun/http-client (timeout, retry, circuit-breaker, SSRF guard, tracing). axios (6 packages) and node-fetch (3) are frozen for new code.

Overlapping utility dependencies — resolution policy#

Overlap Policy
uuid vs nanoid vs hand-rolled New code uses @oshun/ids (uuid/ulid/prefixedId). uuid/nanoid frozen for new code; migrate via the R-10 rollout
bcrypt vs bcryptjs Do not blind-swap. The 6 bcryptjs users are auth-critical services; hash formats are compatible ($2a/$2b) but native bcrypt adds a compile step to their container builds. Swap per-service with its test suite + image build verified — not mechanically
crypto-js Load-bearing in React Native (apps/lilith/mobile encryption-at-rest; Hermes has no node:crypto, and on-device ciphertext must remain decryptable). Any migration (e.g. to @noble/ciphers) must ship a data-format migration for existing installs. apps/lilith/svc-offline shares formats with mobile. Not a mechanical removal
@noble/* vs hash.js/crypto-js for NEW code New cryptographic code uses node:crypto (services) or @noble/* (cross-platform)

The audit's R-17 originally framed bcryptjs/crypto-js as simple removals; investigation during P2 execution (2026-07-16) showed both carry runtime/deployment constraints, recorded above so nobody "cleans them up" mechanically.