DBRaven
Architecture Graph

Startup Monolith

A single deployable application backed by PostgreSQL and Redis: the right starting architecture for most teams. Serves 0–50k users reliably with one deployment pipeline, one on-call runbook, and a team that can hold all of it in their heads.

Web API

Description

The monolith is not a stepping stone to microservices: it is a valid architecture at scale if the team and domain complexity stay manageable. The startup monolith optimizes for delivery velocity, operational simplicity, and reversibility. PostgreSQL provides ACID guarantees and full relational flexibility. Redis handles caching, session state, and background job queuing. A background worker process handles async tasks without introducing a message broker.

The failure modes at this scale are database-centric: connection exhaustion under load, autovacuum pressure on write-heavy tables, and the lack of a circuit breaker for slow external dependencies. None of these require architectural change: they require operational configuration.

Use Cases

  • ·0-to-1 product validating product-market fit
  • ·Internal tools and operational dashboards
  • ·B2B SaaS serving <100 enterprise customers
  • ·Team of 2–8 engineers shipping features weekly
  • ·APIs with predictable workload patterns and <5k RPS

Scale Profile

Entry Point

0–1k DAU

Sweet Spot

1k–50k DAU with up to 2k RPS

Scaling Ceiling

~50k DAU or 3k RPS sustained: connection pressure and long-tail query latency begin to dominate

Typical RPS

10–2k RPS

Architecture Nodes (5)

1 SPOF: PostgreSQL1 stateful: PostgreSQL
ClientsClient

Web browsers, mobile apps, and API consumers making HTTPS requests

external
Application ServerService

Monolithic application handling all business logic, API routing, and background jobs. Stateless: multiple instances are load-balanced.

statelessdeployable
Background WorkerService

Async job processor (Sidekiq, Celery, or similar) pulling from Redis queue for emails, reports, and deferred work.

asyncdeployable
PostgreSQLDatabase
postgresql

Primary relational datastore. All transactional data. Single primary without read replicas at this scale.

statefulSPOFprimary_datastoreacid
RedisCache
redis

In-memory cache for session state, page fragments, and background job queuing. Persistence optional.

cachejob_queue

Dependencies (6)

2 critical path edges. Failure on these directly degrades user-facing requests.

ClientsApplication ServerSynchronouscritical path

HTTPS API requests

All client requests enter the application server over HTTPS. No separate API gateway at this scale.

Timeout: 30s

Application ServerPostgreSQLSynchronouscritical path

Database queries

Synchronous ORM queries. All reads and writes go to the single primary. Connection pool bounded by max_connections.

Timeout: 5s

Application ServerRedisSynchronous

Cache reads/writes

Session storage, cached query results, rate limiting state, and background job enqueuing.

Timeout: 1s

Application ServerBackground WorkerAsync Message

Job enqueue

Web process enqueues background jobs to Redis queue. Worker polls and executes. Decouples async work from request path.

Background WorkerPostgreSQLSynchronous

Async DB writes

Background jobs write results back to PostgreSQL. Same connection pool pressure as web process: must be accounted for.

Background WorkerRedisSynchronous

Job state

Job status tracking and retry coordination stored in Redis.

Failure Propagation

How a failure in one component cascades through the system. Each path documents the mechanism and the mitigation that breaks the chain.

PostgreSQLfails →
Application ServerBackground Worker
connection exhaustion

Mechanism

All app and worker processes queue for connections. Pool fills. New requests timeout.

Mitigation

Configure PgBouncer transaction-mode pooling. Set pool size to max_connections * 0.8.

PostgreSQLfails →
Application Server
lock contention

Mechanism

Long-held row locks from slow queries block subsequent writes to the same rows. Request latency rises.

Mitigation

Set statement_timeout. Use SELECT FOR UPDATE NOWAIT to fail fast on lock contention.

Redisfails →
Application ServerBackground Worker
cold start latency

Mechanism

Redis restart empties session cache and job queue. App falls back to database. Thundering herd on PostgreSQL.

Mitigation

Enable Redis persistence (AOF). Pre-warm cache on restart via background job.

Scaling Transitions

Inflection points where this architecture begins to degrade and what the recommended evolution looks like.

~10k DAU or 500 RPS sustainedPostgreSQL bottleneck

Read queries dominate connection pool. EXPLAIN shows sequential scans on growing tables.

Recommended Action

Add PostgreSQL read replica with routing proxy. Move read-only queries to replica.

Evolution path:single database to read write split
~50k DAU or 2k RPS with read replicaApplication Server bottleneck

Monolith handles all domains in one process. Deploy coupling slows feature teams.

Recommended Action

Introduce module boundaries before splitting services. Domain decomposition without distributed systems cost.

Evolution path:monolith to modular monolith

Patterns Applied

Architectural Notes

  • ·Do not add a message broker (Kafka, RabbitMQ) until Redis queue demonstrably becomes a bottleneck: Redis handles millions of jobs/day without tuning.
  • ·Do not add microservices until domain ownership is well-understood and team exceeds ~15 engineers.
  • ·PgBouncer should be added before the first production deploy: connection overhead at scale is predictable.
  • ·Horizontal scaling of the web process is straightforward since it is stateless. Scale app instances first before adding complexity.

Confidence

Strong

Canonical starting architecture for web applications. Documented by Basecamp, Shopify early stage, GitHub early stage, and thousands of successful startups.