Concept · Requirements & scale
When not to add infrastructure
The cheapest, most reliable component is the one you never run.
2 minsimplicityYAGNI
Every component you add — a cache, a queue, a search cluster, another service — brings an operating cost and new failure modes: it must be deployed, monitored, upgraded, secured, backed up, understood at 3 a.m., and paid for. Good designs add components only when a requirement or a measured bottleneck demands one.
Questions to ask before adding something
- Which requirement fails without it? If you can't name one, don't add it.
- Can an existing component do it? PostgreSQL covers job queues (
FOR UPDATE SKIP LOCKED), full-text search, JSON documents, geospatial queries and pub/sub (LISTEN/NOTIFY) for modest loads. - What's the failure mode? A cache that's empty, a queue that's backed up, a search index that's stale — what does the user see?
- Who operates it? A managed service still needs someone who understands it.
- What does it cost at today's scale, and at 10×?
Common premature additions
| Added | Often unnecessary because |
|---|---|
| Kafka for a few hundred events per second | A database-backed queue or a managed queue is far simpler |
| Microservices for a five-person team | A modular monolith deploys faster with fewer failure modes (monolith vs microservices) |
| A cache in front of a fast, lightly loaded database | It adds staleness and invalidation bugs for little gain |
| Sharding at a few hundred gigabytes | One well-indexed primary handles it |
| Elasticsearch for exact lookups | A database index does it |
Design for change instead
You don't need the component now if you can add it later without a rewrite. Keep interfaces narrow (a Store interface the cache can wrap later), choose partition-friendly keys, and write events to an outbox table even before anything consumes them. Then add infrastructure when capacity estimation or monitoring says you need it.