Adapter Swap Enables Zero-Cost MVP Modes
Executive Summary
Golden-press had a hard dependency on NATS JetStream —publisher.NewPublisher() failure was fatal at startup (line 114 of main.go). This meant the service could not deploy to Railway without a NATS cluster, which is $50+/month infrastructure for zero MVP value (nothing consumes the events yet).
The fix: make NATS_URL empty by default, skip publisher init when empty, pass nil publisher to handler. The handler already handled publish errors gracefully (log + continue). Total change: ~15 lines.
Pattern: Infrastructure Dependencies as Optional Adapters
This extends the ADAPTER-SWAP-PATTERN doctrine already documented in choco-hq. The key insight is that optional infrastructure is not the same as degraded functionality:| Dependency | MVP Mode | Production Mode | User Impact |
|---|---|---|---|
| NATS JetStream | Disabled (no publisher) | Connected (events published) | None — events are for downstream consumers, not users |
| Redis | Disabled (in-memory rate limiting) | Connected (shared rate limiting) | Minimal — rate limits per-instance instead of global |
| the-ledger (gRPC) | Disabled (no Merkle proofs) | Connected (cryptographic verification) | Audit trail unavailable, signatures still work |
| OTel collector | Disabled (structured logs only) | Connected (traces + metrics) | None — observability is for operators, not users |
Implementation Pattern
Key Learning
Fatal startup dependencies should match user-visible dependencies. PostgreSQL is fatal because every endpoint reads/writes data. NATS is optional because event consumers don’t exist yet. The test: “If I remove this dependency, does any HTTP endpoint return a different response?” If no, it’s optional.Session: choco-hq-mvp-gateway-implementation-2026-04-07 Owner: Dev4rno Archive: devarno-cloud/atlas/learnings/2026-04-07-adapter-swap-enables-zero-cost-mvp-modes.md