Workspace IndexDev Notes › An architecture is a record of which failure you agreed to accept

#56PoC

An architecture is a record of which failure you agreed to accept

Every pattern is a purchase: it prevents one failure and introduces another. Studying the catalogue without the failures produces vocabulary rather than judgement — and only two pieces of theory actually predict behaviour, which is a much shorter reading list than it looks.

Not yet scoped, and it is deliberately not a reading plan. Take one system already in this repo — the settlement pipeline is the obvious candidate — and for each component write three lines: what happens if it is slow, what happens if it is down, and what happens if it returns something wrong. That is the failure list, and it is the thing a pattern is an answer to. Then attach patterns to entries rather than reading a catalogue front to back, and for each one write the failure it introduces next to the failure it removes. Separately, and this is the part with actual predictive power: compute the concurrency this system needs from its arrival rate and its latency, and plot queueing delay against utilisation to see where the curve turns. Two formulas, one afternoon.

Why

Architecture is usually studied as a catalogue, and a catalogue is a list of answers with the questions removed. Read front to back, it produces someone who can name a pattern and cannot say when not to use it, which is the definition of cargo cult. The repair is not more reading. It is to notice that every pattern is a trade purchased against a specific failure, and that the failure is the part that transfers between systems while the pattern is the part that does not.

Stating it as a purchase makes the second half visible, and the second half is where the surprises are. Replication prevents node loss and introduces stale reads. A cache prevents load and introduces invalidation, which is genuinely hard. A queue absorbs spikes and introduces unbounded delay and lost ordering. Retries survive transient errors and introduce duplicate work, which is why the-product-is-resume-not-schedule insists the retried unit be idempotent. Microservices decouple teams and reintroduce distributed transactions, plus the fact that every call can now fail. Nobody writes the right column on the slide, and the right column is the whole reason the decision is a decision.

Then the part that is worth memorising, because it is small and it actually predicts. Almost all architecture vocabulary describes; two results predict. Little's Law says concurrency equals arrival rate times latency, which converts a throughput requirement and a latency budget into a number of simultaneous slots — the only routine way to turn a service-level target into capacity. The utilisation curve says queueing delay grows roughly as utilisation over one minus utilisation, so waiting time is not linear in load: at half utilisation the wait is about one service time, at ninety percent it is nine, at ninety-five it is nineteen. Latency does not degrade gradually as a system fills; it degrades hyperbolically, which is why a dashboard reading eighty-five percent is not the comfortable number it appears to be.

Those two, plus a sense of the orders of magnitude, cover most real decisions. A register read, a main-memory read, an SSD read, a same-datacentre round trip and a cross-region round trip are separated by roughly eight orders of magnitude end to end. The exact figures move with hardware and are worth checking rather than quoting, but the ratios do not move, and the ratios are the content. Adding a service call is not a structural choice, it is a choice about which order of magnitude the operation now lives in, and phrasing it that way makes the answer obvious in most cases.

What this leaves out deliberately is the taxonomy, and that is the point. Whether something is called hexagonal, clean, onion or ports-and-adapters matters far less than whether the dependency actually points inward and whether anyone can tell when it stops. steal-the-structure gives the same instruction for reading lists generally: take the shape, not the content. Here the shape is the failure list, and it is the only artifact of an architecture study that survives contact with a different system.

How it works

Every pattern, as a purchase

Pattern The failure it prevents The failure it introduces
Replication Losing a node loses the data Replication lag, and reads that are correct-but-old
Cache Load and latency on the source Invalidation, and a thundering herd on expiry
Queue A spike knocking the consumer over Unbounded delay, lost ordering, and a backlog nobody watches
Retry A transient error becoming a user error Duplicate work — needs idempotency (the-product-is-resume-not-schedule)
Circuit breaker One slow dependency cascading Opening on a false signal, and partial availability that is hard to reason about (circuit-breaker-saga)
Sharding A single node's ceiling Cross-shard transactions and hot keys
Microservices Teams blocking each other Distributed transactions, and every call becoming a failure mode

The right column is the deliverable of an architecture study. Anyone can produce the left one from a summary; only someone who has thought about the system can fill in the right one for their own case.

The two results that predict rather than describe

What it says What it lets you compute
Little's Law Concurrency = arrival rate × latency Turn "500 requests per second at 200ms" into "about 100 slots" — a capacity number from a latency budget
The utilisation curve Wait grows like ρ / (1 − ρ) At 50% load the wait is about one service time; at 90% about nine; at 95% about nineteen

The second is the one that changes behaviour once seen. A queue at 85% utilisation is not 85% of the way to a problem — it is most of the way, and capacity planning that targets high utilisation is buying a latency cliff in exchange for hardware it did not need to save.

The orders of magnitude, which are the actual content

Register, memory, SSD, same-datacentre network, cross-region network — roughly eight orders of magnitude from end to end. The figures move with hardware; the ratios do not. The use of knowing them is not trivia, it is that "just call the other service" becomes a visible decision about which tier the operation now lives in, and most arguments about whether something should be a separate service resolve immediately once that is said out loud.

How to study it so that it transfers

Not front to back. Pick one system you own, and for each component write what happens when it is slow, when it is down, and when it is wrong. That list is portable in a way that pattern names are not: the failures recur across systems, the patterns do not. Then read the catalogue as answers to entries on your list, which also makes it obvious when a pattern is answering a question you do not have — the most common and most expensive form of architecture mistake.

← All Dev Notes · Workspace Index · Top ↑

아키텍처는 어떤 고장을 받아들이기로 했는지의 기록이다

모든 패턴은 구매입니다 — 하나의 고장을 막고 다른 고장을 들여옵니다. 고장을 빼고 카탈로그만 읽으면 판단이 아니라 어휘가 남습니다. 그리고 실제로 행동을 예측하는 이론은 둘뿐이라, 읽을 목록은 보이는 것보다 훨씬 짧습니다.

아직 범위 미정이고, 의도적으로 독서 계획이 아닙니다. 이 저장소에 이미 있는 시스템 하나를 잡고 — 정산 파이프라인이 명백한 후보 — 각 구성요소에 대해 세 줄을 씁니다: 느려지면 어떻게 되나, 죽으면 어떻게 되나, 틀린 값을 돌려주면 어떻게 되나. 그게 고장 목록이고, 패턴은 거기에 대한 답입니다. 그다음 카탈로그를 앞에서부터 읽는 대신 목록의 항목에 패턴을 붙이고, 각 패턴마다 없애는 고장 옆에 들여오는 고장을 같이 적습니다. 그리고 따로 — 실제로 예측력이 있는 부분입니다도착률과 지연에서 이 시스템에 필요한 동시성을 계산하고, 이용률 대비 대기시간 곡선을 그려 어디서 꺾이는지 봅니다. 공식 둘, 반나절.

아키텍처는 보통 카탈로그로 공부되는데, 카탈로그는 질문이 제거된 답 목록입니다. 앞에서부터 읽으면 패턴 이름은 말하지만 언제 쓰지 말아야 하는지는 못 말하는 사람이 만들어지고, 그게 카고 컬트의 정의입니다. 처방은 더 읽는 것이 아닙니다. 모든 패턴은 특정 고장에 대고 산 트레이드라는 것, 그리고 시스템 사이를 이전하는 것은 고장이지 패턴이 아니라는 것을 알아채는 것입니다.

구매라고 말하면 뒷면이 보이고, 놀랄 것은 뒷면에 있습니다. 복제는 노드 손실을 막고 낡은 읽기(stale read)를 들여옵니다. 캐시는 부하를 막고 무효화를 들여오는데, 그건 진짜로 어렵습니다. 큐는 스파이크를 흡수하고 무한정 지연과 순서 상실을 들여옵니다. 재시도는 일시적 오류를 넘기고 중복 수행을 들여오며, 그래서 the-product-is-resume-not-schedule재시도 단위의 멱등성을 고집합니다. 마이크로서비스는 팀을 분리하고 분산 트랜잭션을 다시 들여오며, 덤으로 이제 모든 호출이 실패할 수 있게 만듭니다. 슬라이드에 오른쪽 칸을 적는 사람은 없고, 그 결정이 결정인 이유는 통째로 오른쪽 칸입니다.

그다음이 외울 값어치가 있는 부분입니다. 작고, 실제로 예측하기 때문입니다. 아키텍처 어휘는 거의 전부 서술하고, 예측하는 결과는 둘입니다. Little's Law동시성 = 도착률 × 지연 이라, 처리량 요구와 지연 예산을 동시 슬롯 개수로 바꿔줍니다 — 서비스 목표를 용량으로 바꾸는 유일한 상용 수단입니다. 이용률 곡선은 대기시간이 대략 이용률 ÷ (1 − 이용률) 로 자란다고 말합니다. 즉 대기시간은 부하에 선형이 아닙니다 — 이용률 50%에서 서비스 시간의 약 1배, 90%에서 9배, 95%에서 19배. 시스템이 차오를 때 지연은 서서히가 아니라 쌍곡선으로 무너지고, 그래서 85%를 가리키는 대시보드는 보이는 것만큼 편안한 숫자가 아닙니다.

이 둘에 자릿수 감각을 더하면 실제 결정의 대부분이 덮입니다. 레지스터 읽기, 메인메모리 읽기, SSD 읽기, 같은 데이터센터 왕복, 대륙 간 왕복은 끝에서 끝까지 대략 여덟 자릿수 떨어져 있습니다. 정확한 수치는 하드웨어를 따라 움직이므로 인용하기보다 확인할 것이지만, 비율은 움직이지 않고, 내용은 비율입니다. 서비스 호출을 하나 더하는 것은 구조 선택이 아니라 그 연산이 이제 어느 자릿수에 사는가에 대한 선택이고, 그렇게 말하면 대부분의 경우 답이 자명해집니다.

의도적으로 뺀 것은 분류학이고, 그게 요점입니다. 그것이 헥사고날이냐 클린이냐 어니언이냐 포트앤어댑터냐는, 의존성이 실제로 안쪽을 향하는가, 그리고 그것이 깨졌을 때 누가 알아챌 수 있는가보다 훨씬 덜 중요합니다. steal-the-structure 가 읽을거리 일반에 대해 같은 지시를 합니다 — 내용이 아니라 구조를 가져와라. 여기서 그 구조가 고장 목록이고, 그것만이 다른 시스템과 만나도 살아남는 유일한 산출물입니다.

동작 방식

모든 패턴을, 구매로

패턴 막는 고장 들여오는 고장
복제 노드 하나 잃으면 데이터도 잃음 복제 지연, 그리고 맞지만 낡은 읽기
캐시 원본에 걸리는 부하와 지연 무효화, 만료 시 thundering herd
스파이크가 소비자를 넘어뜨림 무한정 지연, 순서 상실, 아무도 안 보는 적체
재시도 일시적 오류가 사용자 오류가 됨 중복 수행 — 멱등성 필요 (the-product-is-resume-not-schedule)
서킷 브레이커 느린 의존성 하나가 연쇄로 번짐 오신호로 열림, 그리고 추론하기 어려운 부분 가용성 (circuit-breaker-saga)
샤딩 단일 노드의 천장 교차 샤드 트랜잭션과 핫키
마이크로서비스 팀이 서로를 막음 분산 트랜잭션, 그리고 모든 호출이 고장 양식이 됨

아키텍처 공부의 산출물은 오른쪽 칸입니다. 왼쪽은 요약만 봐도 누구나 적고, 오른쪽을 자기 경우에 대해 채울 수 있는 사람은 그 시스템을 생각해 본 사람뿐입니다.

서술이 아니라 예측하는 결과 둘

무엇을 말하나 무엇을 계산하게 해주나
Little's Law 동시성 = 도착률 × 지연 "초당 500 요청, 200ms" 를 "동시 슬롯 약 100개" 로 — 지연 예산에서 용량 숫자
이용률 곡선 대기 ≈ ρ / (1 − ρ) 이용률 50%면 서비스 시간의 약 1배, 90%면 약 9배, 95%면 약 19배

한 번 보면 행동이 바뀌는 쪽은 두 번째입니다. 이용률 85%인 큐는 문제까지 85% 온 것이 아니라 거의 다 온 것이고, 높은 이용률을 목표로 하는 용량 계획은 아낄 필요도 없던 하드웨어와 맞바꿔 지연 절벽을 사는 것입니다.

자릿수 — 실은 이게 내용입니다

레지스터, 메모리, SSD, 같은 데이터센터 네트워크, 대륙 간 네트워크 — 끝에서 끝까지 대략 여덟 자릿수. 수치는 하드웨어를 따라 움직이고 비율은 안 움직입니다. 이걸 아는 쓸모는 잡학이 아니라, "그냥 다른 서비스를 부르면 되지" 가 그 연산이 이제 어느 층에 사는가에 대한 눈에 보이는 결정으로 바뀐다는 것입니다. 그리고 무언가를 별도 서비스로 뗄지에 대한 논쟁 대부분은 그 말을 소리내어 하는 순간 정리됩니다.

이전되게 공부하는 법

앞에서부터 읽지 않습니다. 내가 소유한 시스템 하나를 골라, 각 구성요소가 느릴 때·죽을 때·틀릴 때 무슨 일이 생기는지 씁니다. 그 목록은 패턴 이름과 달리 이식 가능합니다고장은 시스템을 건너 반복되고, 패턴은 그렇지 않습니다. 그다음 카탈로그를 내 목록 항목에 대한 답으로 읽으면, 어떤 패턴이 내게 없는 질문에 답하고 있는지도 자명해집니다 — 그게 가장 흔하고 가장 비싼 형태의 아키텍처 실수입니다.

← 전체 개발 노트 · 워크스페이스 인덱스 · 맨 위 ↑