Architecture Review — Sample
A worked example of reviewing a system against how it is actually used — where load and change concentrate, which couplings cost, and the recommendation that follows from evidence rather than from taste.
Markdown. No sign-up, no email.
This is an illustrative example. The system and figures are invented to show the shape of a review that produces decisions. Copy the structure; measure your own system.
The review deliberately avoids architectural preference. Every recommendation is supported by either an incident, a measurement, or a change-history count.
Architecture review — order platform#
| System | Order capture, pricing, fulfilment, invoicing, reporting |
| Age | 6 years, 5 services, one shared database |
| Method | Change history, incident record, load measurement, dependency mapping |
| Prepared for | Engineering leadership |
1. How it is actually used#
| Orders per day | 42,000 |
| Peak, as a multiple of median hour | 3.1× |
| Read to write ratio | 40:1 |
| Reporting queries per day | 900 |
| Growth, 12 months | 18% |
The read-to-write ratio is the most consequential number in this review, and it was not known before the review. The system is designed as though writes dominate, and reads — including every reporting query — go to the same database as order capture.
2. Where change concentrates#
| Component | Share of code | Share of changes | Incidents |
|---|---|---|---|
| Pricing | 11% | 38% | 9 |
| Order capture | 19% | 17% | 4 |
| Fulfilment | 24% | 14% | 6 |
| Invoicing | 18% | 21% | 3 |
| Reporting | 28% | 10% | 2 |
Pricing changes constantly — it is where the business expresses itself — and it is the smallest component. It is also called synchronously by order capture, which is section 4.
3. Coupling#
| Coupling | Type | Cost in the period |
|---|---|---|
| All 5 services → one database | Shared data store | 6 of 24 incidents |
| Order capture → pricing | Synchronous | 9 incidents, all pricing-caused |
| Invoicing → fulfilment | Synchronous | 2 incidents |
| Fulfilment → carrier API | Synchronous, external | 4 incidents |
| Reporting → the same database | Shared | 3 incidents |
The shared database is the largest structural finding. Five services with no business relationship share a failure domain. Twice this year a reporting query has degraded order capture; on both occasions the reporting team was unaware of the incident and the order team had no way to see the cause.
4. The pricing coupling#
Worth its own section, because it produces the most incidents and the fix is not obvious.
Order capture calls pricing synchronously. Pricing changes most often. The most frequently changed component sits inside the availability path of the most business-critical one.
| Pricing incidents in 12 months | 9 |
| Of those, causing order capture to fail | 9 |
| Median duration | 14 min |
| Orders lost or delayed | ~3,900 |
The naive fix — make it asynchronous — is wrong. A price is needed to accept an order; there is no meaningful order without one. This is a genuine coupling and the honest response is to make it bounded rather than to pretend it is not there.
Recommended instead: a timeout with an explicit fallback to the last published price list, plus a circuit breaker. The fallback is not as good as live pricing and it is much better than refusing orders. The business rule — how long a stale price may be used, and for which product categories — is a decision for the commercial team, not for engineering.
5. Load#
| Measured | Provisioned for | |
|---|---|---|
| Order capture, peak | 340 req/min | 2,000 |
| Pricing, peak | 340 req/min | 400 |
| Reporting, peak | 90 queries/min | shared |
| Database connections at peak | 780 of 800 | 800 |
The connection pool is the binding constraint and nobody knew. At peak the system is 20 connections from refusing work, and the largest single consumer is reporting — long-running queries holding connections while order capture waits.
This also explains an unexplained class of incident: three "slow order capture" reports correlate exactly with a monthly reporting job.
6. What is working#
Recorded because a review of only problems produces a rewrite proposal.
- Service boundaries follow the business. Order, pricing, fulfilment and invoicing are real domains, not layers. This is the hard part and it is right.
- Order capture is idempotent. Duplicate submissions are handled correctly, which has prevented several incidents from becoming data problems.
- The carrier integration has a timeout and a queue. The one external dependency is the best-protected boundary in the system.
- Deployment is per service and has been for two years.
7. Recommendations#
- Separate reporting from the operational database. A read replica, with reporting pointed at it. Addresses 3 incidents, the connection-pool constraint, and the monthly correlation. Roughly two weeks and no application change.
- Bound the pricing call — timeout, fallback to the last published list, circuit breaker. Addresses 9 incidents. Needs a commercial decision on stale-price tolerance first.
- Give each service its own schema within the shared instance, as a step toward separate stores. Removes accidental cross-service queries, of which the review found 14.
- Raise the connection pool and alert at 80%. A one-line change that removes the current silent ceiling.
- Do not split pricing into smaller services. It changes often because the business changes often, not because it is too large. Splitting it would distribute a coupling rather than remove one.
- Do not rewrite fulfilment. It has 6 incidents and 14% of changes, and every one of the incidents traces to the carrier API rather than to the code.
Deliberately not recommended: a move to full service isolation with separate databases per service. Recommendations 1 and 3 capture most of the benefit for a fraction of the work, and the remainder can be argued when the first two have been measured.
Notes on using this format#
Measure how the system is used before reviewing how it is built. The 40:1 read-to-write ratio was unknown, and it reframed the entire review.
Count incidents per coupling. It converts "the shared database is bad practice" into "the shared database caused 6 of 24 incidents", which is a sentence that gets funded.
Say what not to change. Two of the six recommendations are refusals, and both are for components that look like obvious candidates and cost nothing.