Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,14 @@ k6, Locust.
`float("5.10") == 5.1` is a known trap.
- **No positional language** anywhere (slides or site): no "above / below / next slide /
previous section / see slide N". Cross-reference the **concept**, not a number.
- Chapters end with `### Cross-check it yourself` + an italic `*Verification status: …*`
footer. **Flip the footer to verified once `examples/NN-*/` runs green.**
- Hands-on chapters end with a `## Build, run, observe` section: the example's
`verify.sh` command (start one language's stack, run the language-agnostic
checks) and what it asserts, plus the observe guidance. **No reader-facing
`*Verification status: …*` footer** on the page: the per-chapter run records
live in `_plans/verification-log.md` (the `plans` collection is
`output: false`). Conceptual chapters have no Build, run, observe section.
When an example's `verify.sh` runs green, update `_plans/verification-log.md`,
not a chapter footer.
- **Validate before commit:** front-matter parses; raw-guard balance; **0 unguarded `{{`**;
each codetab block-count == its `langs` count; referenced figures exist (`.svg` + `.excalidraw`);
**0 positional terms**.
Expand Down
5 changes: 0 additions & 5 deletions _docs/00-setting-up.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,3 @@ concerns (workflows and the platform planes); and finally anti-patterns as a
reflective close. The deep-dive appendices at the end go deeper on the questions
that always come up (protocols, versioning, WebSockets, sagas, and more) and
can be read on demand.

---
*Verification status: conceptual chapter; no runnable code. The patterns named
here are defined and applied in their own chapters, where the code ships with a
runnable example per language.*
19 changes: 14 additions & 5 deletions _docs/01-cloud-native-principles.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,20 @@ The same two ideas appear in every tab:
Notice what *isn't* here: no retry logic, no scaling code, no port-binding
plumbing. Those are the right column of Figure 1.3: the platform's job.

### Cross-check it yourself
## Build, run, observe

```bash
cd examples/01-cloud-native-principles/python # or any of the six language stacks
docker compose up -d --build --wait
cd ..
./verify.sh
```

`verify.sh` runs the language-agnostic end-to-end checks against the running stack (13/13 in
each of the six languages), asserting the service reports its name, version and config
source from the environment (Factor III), liveness stays `200` while readiness flips from
`200` to `503` and back as Postgres is stopped and restarted, and a CRUD round trip
(create an order, list it back) succeeds while the database is up.

With the service running, the probes are just HTTP. Hit liveness and readiness
with `curl` and confirm liveness returns healthy while the database is down but
Expand All @@ -300,7 +313,3 @@ database and back as you start it, without the process ever restarting.

The code is in [`examples/01-cloud-native-principles/`](https://github.com/patterncatalyst/cloud-native-design-patterns/tree/main/examples/01-cloud-native-principles/). The run script there builds
and runs it; its `README.md` covers what it does and how to drive it.

---
*Verification status: verified; [`examples/01-cloud-native-principles/`](https://github.com/patterncatalyst/cloud-native-design-patterns/tree/main/examples/01-cloud-native-principles/) passes 13/13 checks in each of the six languages on Docker Engine (2026-10-13)
(health probes, config from environment, CRUD, readiness flip on dependency failure).*
20 changes: 15 additions & 5 deletions _docs/02-communications.md
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,21 @@ piles onto the struggling service in a retry storm. Putting the policy in the me
means one bounded, observable rule for every caller, instead of each team
re-inventing (and mis-tuning) retries in code.

### Cross-check it yourself
## Build, run, observe

```bash
cd examples/02-communications/python # or any of the six language stacks
docker compose up -d --build --wait
cd ..
./verify.sh
```

`verify.sh` runs the language-agnostic end-to-end checks against the running stack (10/10 in
each of the six languages), asserting a create returns `201` with an id and status, a bad
body returns `422` before business logic runs, cursor pagination returns a page with a
`next_cursor`, an order with available stock comes back confirmed while one exceeding stock
is rejected (the gRPC stock reservation), a GraphQL orders query returns data, and the
`order.placed` Kafka topic exists after a create.

Use plain tools. `curl` and Postman exercise the REST contract: confirm a create
returns **201** and that a bad body returns **400** before your logic runs.
Expand All @@ -411,7 +425,3 @@ bounded retries behave under pressure rather than trusting they do.

The code is in [`examples/02-communications/`](https://github.com/patterncatalyst/cloud-native-design-patterns/tree/main/examples/02-communications/). The run script there builds and runs
it; its `README.md` covers what it does and how to drive it.

---
*Verification status: verified: [`examples/02-communications/`](https://github.com/patterncatalyst/cloud-native-design-patterns/tree/main/examples/02-communications/) passes 10/10 checks in each of the six languages on Docker Engine (2026-10-13)
(REST create and validation (201, 422), cursor pagination, order confirmation and rejection driven by the gRPC stock reservation, a GraphQL orders query, and the order.placed Kafka topic).*
19 changes: 14 additions & 5 deletions _docs/03-composition.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,20 @@ distance), and it couples only to their contracts (low strength). A call chain
violates it: services that are far apart couple at the functional level, which is
exactly why it becomes a distributed monolith.

### Cross-check it yourself
## Build, run, observe

```bash
cd examples/03-composition/python # or any of the six language stacks
docker compose up -d --build --wait
cd ..
./verify.sh
```

`verify.sh` runs the language-agnostic end-to-end checks against the running stack (8/8 in
each of the six languages), asserting the gateway's health endpoint and the backing order
API respond, a GraphQL query without the `stock` field omits it (no inventory call), a
query with `stock` resolves it from the gRPC inventory service, the gateway logs a single
batched DataLoader call across the backend skus, and a single-order lookup by id resolves.

The gateway is just HTTP. Send the same query with `curl` or Postman and request
`stock` in one call, then omit it in another. Confirm the gateway only calls
Expand All @@ -272,7 +285,3 @@ list size; with a DataLoader it stays flat. That flat line is the N+1 fix workin

The code is in [`examples/03-composition/`](https://github.com/patterncatalyst/cloud-native-design-patterns/tree/main/examples/03-composition/). The run script there builds and runs it;
its `README.md` covers what it does and how to drive it.

---
*Verification status: verified; [`examples/03-composition/`](https://github.com/patterncatalyst/cloud-native-design-patterns/tree/main/examples/03-composition/) passes 8/8 checks in each of the six languages on Docker Engine (2026-10-13)
(GraphQL gateway fan-out to the REST order API and the gRPC stock service, selective stock-field resolution, DataLoader batching of stock lookups into one gRPC call, single-order lookup).*
19 changes: 14 additions & 5 deletions _docs/04-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,20 @@ pattern; the choreography-versus-orchestration trade-off, how a saga holds its s
and how a later step gets an earlier step's data are taken up in depth in **Appendix D
· Sagas**.

### Cross-check it yourself
## Build, run, observe

```bash
cd examples/04-data/python # or any of the six language stacks
docker compose up -d --build --wait
cd ..
./verify.sh
```

`verify.sh` runs the language-agnostic end-to-end checks against the running stack (8/8 in
each of the six languages), asserting Kafka Connect comes up and the Debezium outbox
connector reaches `RUNNING`, a create writes both the order row and its outbox row in one
transaction, and the Debezium relay publishes the outbox row to the `order.placed` Kafka
topic with the order's payload intact.

You do not have to trust that the commit and the event stay in step: you can
watch it. With the example running, stop the Kafka broker, place an order, and
Expand All @@ -329,7 +342,3 @@ without a re-request, is the property the outbox buys you.

The code is in [`examples/04-data/`](https://github.com/patterncatalyst/cloud-native-design-patterns/tree/main/examples/04-data/). The run script there builds and runs it; its
`README.md` covers what it does and how to drive it.

---
*Verification status: verified; [`examples/04-data/`](https://github.com/patterncatalyst/cloud-native-design-patterns/tree/main/examples/04-data/) passes 8/8 checks in each of the six languages on Docker Engine (2026-10-13)
(transactional write of order and outbox row, Debezium outbox connector running, relay of the outbox event to the order.placed Kafka topic with its payload).*
21 changes: 16 additions & 5 deletions _docs/05-event-driven.md
Original file line number Diff line number Diff line change
Expand Up @@ -1284,7 +1284,22 @@ The throughline of the whole chapter: an event-driven system trades immediate co
and a single in-the-moment truth for decoupling, autonomy, scale, and a complete, replayable
history. Spend that trade where it pays, and avoid it in the few places it doesn't.

### Cross-check it yourself
## Build, run, observe

```bash
cd examples/05-event-driven/python # or any of the six language stacks
docker compose up -d --build --wait
cd ..
./verify.sh
```

`verify.sh` runs the language-agnostic end-to-end checks against the running stack (10/10 in
each of the six languages), asserting a placed order publishes to `order.placed`, both the
`shipping-group` and `notification-group` consumer groups exist and each independently
writes its own row for the order (fan-out, not round-robin), and replaying the same event
through the topic does not create a second shipment or notification row (idempotent
consumers under a redelivered duplicate). The same script also drives the Kubernetes
variant: Appendix R runs it on minikube and Appendix S on OpenShift Local.

Produce one `order.placed` and watch two independent consumer groups receive it:
the fan-out is real, not round-robin. Then stop a consumer mid-handler (before it
Expand All @@ -1295,7 +1310,3 @@ redelivery is the at-least-once guarantee, and the reason your handler dedupes.
The code is in [`examples/05-event-driven/`](https://github.com/patterncatalyst/cloud-native-design-patterns/tree/main/examples/05-event-driven/). The run script there builds and runs
it; its `README.md` covers what it does and how to drive it. The same example, with Kafka managed by
the Strimzi operator, also runs on a Kubernetes cluster; Appendix R covers that deployment on minikube and Appendix S covers OpenShift Local.

---
*Verification status: verified; [`examples/05-event-driven/`](https://github.com/patterncatalyst/cloud-native-design-patterns/tree/main/examples/05-event-driven/) passes 10/10 checks in each of the six languages on Docker Engine (2026-10-13) and on minikube (2026-10-11, Appendix R), and 10/10 in five languages on OpenShift Local 4.22.14 (2026-10-11, Appendix S)
(event publication to order.placed, fan-out to two independent consumer groups (shipping and notification), and idempotent consumers under a redelivered duplicate event).*
21 changes: 16 additions & 5 deletions _docs/06-stream-processing.md
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,22 @@ lever: true scale-to-zero when the topic is quiet, springing back the moment lag
builds. Picking the signal (lag for events, request rate for HTTP) is the whole
point; scaling a backlog-bound consumer on CPU would miss the load entirely.

### Cross-check it yourself
## Build, run, observe

```bash
cd examples/06-stream-processing/python # or any of the six language stacks
docker compose up -d --build --wait
cd ..
./verify.sh
```

`verify.sh` runs the language-agnostic end-to-end checks against the running stack (11/11 in
each of the six languages), asserting orders for two merchants land in the derived
`revenue.by-merchant` topic with a per-merchant aggregation, the `stream-processor` consumer
group exists, pausing that consumer and sending a burst of orders makes its lag on
`order.placed` rise above zero, resuming it drains the lag back down, and the burst's
merchant eventually shows up in the revenue stream (the windowed aggregation catching up
end to end).

Make lag visible, then make it move. Pause the `payment-consumer`, publish a burst
of `order.placed` with `hey` driving `order-service`, and watch the consumer-group
Expand All @@ -337,7 +352,3 @@ behaviour to confirm.

The code is in [`examples/06-stream-processing/`](https://github.com/patterncatalyst/cloud-native-design-patterns/tree/main/examples/06-stream-processing/). The run script there builds and
runs it; its `README.md` covers what it does and how to drive it.

---
*Verification status: verified: [`examples/06-stream-processing/`](https://github.com/patterncatalyst/cloud-native-design-patterns/tree/main/examples/06-stream-processing/) passes 11/11 checks in each of the six languages on Docker Engine (2026-10-13)
(per-merchant revenue aggregation onto a derived Kafka topic, the stream-processor consumer group, consumer lag that builds while the processor is paused and drains on resume, and the burst appearing in the revenue stream).*
5 changes: 0 additions & 5 deletions _docs/07-workflows-and-jobs.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,3 @@ the pod enter `Completed`, not `Running`. Separately, push a heavy task through
HTTP handler and watch the client time out. Then move the same task behind a queue
worker and watch the request return immediately while the work drains in the
background. That contrast is the whole rule.

---
*Verification status: conceptual chapter with an illustrative Kubernetes manifest;
no per-language runnable example. The coordination patterns it names are made
concrete in the saga appendix.*
5 changes: 0 additions & 5 deletions _docs/08-api-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,3 @@ limit with `hey` and confirm the gateway returns `429` with a `Retry-After` rath
than letting the load through: that response is the runtime plane doing its job as
configuration. The contract-plane enforcement is demonstrated in the registry
chapter, where a breaking change is rejected at publish time.

---
*Verification status: conceptual chapter: no per-language runnable code. The
runtime-plane and contract-plane behaviours it describes are exercised in the
security, registry, and Appendix B chapters.*
20 changes: 15 additions & 5 deletions _docs/09-api-registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -330,15 +330,25 @@ func isCompatible(group, artifactID string, schema []byte) (bool, error) {
}
```

### Cross-check it yourself
## Build, run, observe

```bash
cd examples/09-api-registry
docker compose up -d --build --wait
./verify.sh
```

This example is language-agnostic: Apicurio Registry is the only service under
test, so there is one stack, not six. `verify.sh` runs the end-to-end checks
against the running registry (8/8), asserting schema registration, the
`BACKWARD` compatibility rule, rejection of a breaking change (renamed field)
with `400` and a `RuleViolationException`, acceptance of an additive change
(new optional field) with `200`, and versioned retrieval of the latest schema
content.

Prove the gate bites. Register `order-placed.avsc`, then make a breaking
change (rename a required field) and `curl` the new version: you should get a
`400`, and the CI step should exit non-zero. Then make an additive change (a new
*optional* field) and confirm it returns `200` and publishes a new version. The
breaking change failing the build and the additive change passing it is the entire
point of the registry.

---
*Verification status: verified; [`examples/09-api-registry/`](https://github.com/patterncatalyst/cloud-native-design-patterns/tree/main/examples/09-api-registry/) passes 8/8 checks on Docker Engine (2026-10-13)
(schema registration, BACKWARD compatibility rule, rejection of a breaking change with 400, acceptance of an additive change, versioned retrieval).*
5 changes: 0 additions & 5 deletions _docs/10-api-metadata.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,3 @@ follow its lineage downstream: confirm you can see, without asking anyone, which
tables and APIs consume it and which team owns each. Then check that an asset
carries its owner and PII tags. Getting that impact list from the catalog rather
than from a post-incident retro is the whole point.

---
*Verification status: conceptual chapter: no per-language runnable code. The
discovery, lineage, and trust capabilities it describes are exercised against a
running OpenMetadata catalog in the example stack.*
22 changes: 17 additions & 5 deletions _docs/11-observability.md
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,23 @@ The shape (keep errors, keep slow, sample the rest) is the one most teams want:
you never drop the traces you'd investigate, and you pay full storage only
for the boring majority you sample down.

### Cross-check it yourself
## Build, run, observe

```bash
cd examples/11-observability/python # or any of the six language stacks
docker compose up -d --build --wait
cd ..
./verify.sh
```

`verify.sh` runs the language-agnostic end-to-end checks against the running
stack (10/10 in each of the six languages), asserting: the order-service health
check; an order placed over REST returns `201` and reaches `confirmed` status
(stock reserved via gRPC); the `trace_id` logged by order-service is correlated
with the request; that trace is found in Tempo with order-service spans; the
inventory-service span (propagated over gRPC) is part of that same trace, not a
different one; and the `orders.placed` and `stock.reservations` counters show up
in Prometheus.

Prove the correlation with the house tools; no heavy framework needed. Drive a
request through `order-service` with `curl`, grab the `trace_id`, and find that
Expand All @@ -441,7 +457,3 @@ five services. Then push load with `hey` (HTTP) and `ghz` (gRPC) and watch the
metrics move and the tail sampler keep the slow and errored traces while dropping
the rest. Seeing one request as one waterfall is the moment observability stops
being three disconnected tools.

---
*Verification status: verified: [`examples/11-observability/`](https://github.com/patterncatalyst/cloud-native-design-patterns/tree/main/examples/11-observability/) passes 10/10 checks in each of the six languages on Docker Engine (2026-10-13)
(trace propagation, metric export, structured log correlation, LGTM stack integration).*
Loading
Loading