The first thing I noticed while studying architectures for Codelit's reference library was how familiar the components were. Databases, queues, caches, workers. The hard part was not discovering another technology. It was understanding why a team put a boundary in one place rather than another.
is a study model of services, data stores and failure boundaries, reconstructed from public sources to explain a design rather than certify a company's current infrastructure.
This is what I took from a set of 55 architecture studies. It is not a statistical survey, and the diagrams should not be mistaken for complete production inventories.
Why do queues appear so often in reference architectures?
Queues appear when a system needs to accept work independently of processing it. That separation can absorb bursts and isolate a slow consumer from a user-facing request. It also creates a new obligation: track backlog, retries and the age of unfinished work.
The practical question is not “Should this system have Kafka?” It is “Does this operation need to finish before I answer the user?”
For an image upload, storing the original may need to finish immediately while thumbnail generation can happen later. For a payment, telling the user “accepted” and telling them “paid” are different promises.
Once the work moves to a queue, draw the failure path too:
- What happens when a message arrives twice?
- How long can the oldest job wait?
- Who investigates a job that exhausts its retries?
- Can the producer keep accepting work faster than consumers can finish it?
A monolith can use a queue. A distributed system can have a sensible synchronous path. Deployment shape does not answer the timing question.
When is caching the right scaling move?
Caching is the right move when repeated work dominates a measured bottleneck and the product can define acceptable freshness. A useful cache design explains misses, invalidation and failures. Otherwise the cache can move the bottleneck or serve incorrect data faster.
Before adding capacity, I would ask whether we can avoid doing the work at all. But I would also ask what happens when the cache is empty.
A design that survives only with a warm cache has a recovery problem. A popular key can create a stampede. A cached permission decision can outlive the permission. Those are not arguments against caching; they are part of designing it.
| Decision | Question to answer |
|---|---|
| Cache key | Which inputs actually determine the result? |
| Freshness | How stale may this value be? |
| Miss behavior | Can the source absorb cold-start traffic? |
| Invalidation | What event makes the cached value unsafe? |
| Failure | Does the request fail open, fail closed or use stale data? |
The answer can be different for a product image and an account balance. The same “Redis” box does not mean the same design.
What does Stripe's idempotency pattern actually guarantee?
Stripe's idempotency mechanism allows a client to retry a supported request using the same key and parameters without executing the same operation again while the result is retained. The guarantee has documented boundaries, so it should be treated as an API contract rather than a general exactly-once promise.
Stripe's documentation explains that saved results can include failures, that parameter mismatches are rejected and that keys can be removed after they are at least 24 hours old. Validation failures and concurrent conflicts have additional retry considerations.
The design lesson I take from this is to name the logical operation first. An order attempt gets a stable key; a genuinely new attempt gets a new one. Retrying with a new key defeats the mechanism.
The rest of the application still needs durable state and reconciliation. A provider accepting a request and your worker recording that acceptance are two separate events. That gap is also central to agent workflow orchestration.
What does Netflix's delivery model change about the question?
Netflix's Open Connect changes where content is served by placing delivery infrastructure close to viewers through ISP partnerships and interconnection. The lesson is to question data movement before scaling a distant origin. It is not evidence that every application should build a private CDN.
Netflix describes Open Connect as its content delivery network, with embedded appliances and peering arrangements. That is a concrete example of distribution becoming an architecture decision.
For a smaller product, the same question can lead to an ordinary CDN, regional storage or a different asset format. Copy the reasoning about distance and demand. Do not copy the infrastructure budget.
When do service boundaries earn their complexity?
Service boundaries earn their complexity when independent deployment, ownership, scaling or failure isolation solves a real constraint. Splitting code alone does not create those properties. Shared state and synchronous dependencies can preserve the coupling while adding network and operational failure modes.
A gateway is a good example of why a box count is misleading. One gateway on a diagram may represent a redundant managed service, not a single process. Several gateways may isolate deployments, or they may merely duplicate configuration.
I would ask which changes can ship independently, which failures remain local and who owns recovery. That is a better review than declaring one gateway wrong or several hundred services impressive.
Breaking a diagram deliberately is useful for testing the declared dependencies. It is still a model; undeclared coupling needs evidence from the actual system.
What should you try before adding another component?
Try the smallest intervention that addresses the measured constraint, and write down the failure mode it introduces. There is no honest percentage assigning most scaling problems to caches or the remainder to sharding. Different workloads reach different limits.
| Observed constraint | Candidate intervention | Cost to investigate |
|---|---|---|
| Repeated expensive reads | Query improvement or caching | Freshness and invalidation |
| Read load exceeds one primary | Read replicas | Replication lag and routing |
| Slow work blocks responses | Asynchronous processing | Duplicate work and backlog |
| One hot partition dominates | A different key or partition strategy | Migration and skew |
| Teams cannot ship independently | A clearer module or service boundary | Contracts and operating ownership |
This is also where design-time cost estimation belongs. A new component should arrive with a reliability argument and a budget, not just an arrow.
How do you turn a reference diagram into real understanding?
Turn a reference diagram into an explanation you can reconstruct without looking at it. Follow one request, name the state it changes and describe what happens if the next step fails. The gaps in that explanation are the next things to study.
I use this loop:
- Read the primary source and note its date and scope.
- Redraw one path rather than the whole company's architecture.
- Label what is known, inferred or deliberately simplified.
- Change one constraint and explain which decisions must change.
- Compare the result with the source again.
That is the distinction behind teaching system design through a canvas. A polished diagram makes a design easier to discuss. It does not remove the need to understand it.
The Codelit template library is a place to start the exercise. The goal is not to reproduce the picture. It is to explain why each component deserves to remain.
Questions people actually ask
- What do reference architectures teach beyond the component list?
- The useful lesson is the constraint behind each component: which work must finish now, which can wait, what data must stay consistent and what failure the system tolerates. A reference diagram is a study model reconstructed from public material, not an authoritative map of a company's current infrastructure.
- Do I need a message queue in every architecture?
- No. A queue helps when work can happen asynchronously, bursts need buffering or consumers need independent retries. It also introduces backlog, duplicate delivery and operational work. A simple synchronous path is reasonable when its latency and failure behavior meet the requirement.
- Is caching better than microservices for scaling?
- The comparison depends on the bottleneck. Caching removes repeated work when stale data is acceptable. Service separation can support independent scaling, ownership and isolation. Neither is a universal first step; measure the workload and name the constraint before choosing one.
- What does a Stripe idempotency key guarantee?
- A supplied idempotency key lets Stripe recognize retries of a supported request and return the stored result rather than repeat the operation. Keys must be reused for the same logical attempt with matching parameters, and Stripe documents retention and execution-related limits.
- How should I practice with a reference architecture?
- Read the source and draw one request path yourself. State its assumptions, remove a component and explain what changes. Then introduce a failure and describe detection and recovery. The exercise is useful when it exposes a question the finished diagram concealed.