Skip to content
PATTERN LIBRARY

Pattern Template

The shape of a pattern library entry at each of three depths: STUB → OUTLINE → DEEP. One file per pattern; status in frontmatter changes; content grows.

The Pattern Library is the durable knowledge artifact ROOT produces. Phase docs go stale, tools get replaced, projects retire — but the patterns survive because they describe categories of problem, not specific implementations. This template is how every entry in that library is shaped, regardless of whether it’s brand-new (STUB) or backed by years of operational hours (DEEP).

The single-file model matters. URLs stay valid as the pattern deepens; cross-references from phase docs, runbooks, ADRs, and weekly logs continue to resolve; git history is the audit trail of how your understanding grew. Splitting STUB/OUTLINE/DEEP into separate files would shatter that — don’t.

Pattern depth is the contract that ties this template to the rest of ROOT. STUB is cheap and you should create one whenever a phase first references a pattern. OUTLINE is the proof you’ve engaged with the pattern through investigation and a phase. DEEP is reserved for patterns you’ve operated on for 3+ months — anything less is fiction.


The depth ladder

STUB → OUTLINE → DEEP
~15 lines 3-10 pages 10-30 pages
The seed. Heading-level Full pattern-first
structure. treatment with
anti-patterns +
operational lessons.
You write You write at You write after
this from the phase that 3+ months operating
imagination first touches something that
+ public the pattern. depends on it.
sources.

Update the same file in place. Change status: in frontmatter, expand content. URLs stay valid; cross-references stay valid; git history is the audit trail.


STUB shape (~15 lines)

Where every pattern starts. Identifier + 1-paragraph definition + 1-paragraph trade-off + a “deepen this when…” footer.

---
title: "<Pattern Title>"
slug: <kebab-case>
status: STUB
category: <one of 10 categories>
canonical-implementations: [tool1, tool2, tool3]
first-deepening: Year N Phase M
---
# <Pattern Title>
The pattern: 1-2 sentences explaining what category of problem this addresses.
The trade-off: 1-2 sentences contrasting the choices any implementation makes (e.g., "X-or-Y trade-off").
[Deepen this entry when first hit in Phase M.]

Worked example at STUB depth — control-loops:

---
title: "Control Loops"
slug: control-loops
status: STUB
category: foundations
canonical-implementations: [kubernetes-controller, argocd-application-controller, terraform-apply, systemd]
first-deepening: Year 1 Phase 7
---
# Control Loops
The pattern: a control loop continuously observes desired state, observes actual state, and takes action to drive actual toward desired. The loop is what makes a system "self-healing" — recovery is not a special case, it's the default behavior of every iteration.
The trade-off: tight loops (sub-second) react fast but consume resources and amplify metric noise; loose loops (seconds-to-minutes) are cheap but allow longer divergence windows. Every implementation picks a point on this axis.
[Deepen this entry when first hit in Phase 7 (Kubernetes + GitOps).]

That’s it. ~15 lines. The point is to give phase docs a place to link to; the content fills in later.


OUTLINE shape (3-10 pages)

When a phase first touches the pattern, you promote STUB → OUTLINE during that phase. Add structured sections from your investigation.

---
title: "<Pattern Title>"
slug: <kebab-case>
status: OUTLINE ← changed from STUB
category: <category>
canonical-implementations: [...]
last-deepened: YYYY-MM-DD ← added
related: [<other-pattern>, <other-pattern>]
---
# <Pattern Title>
> The pattern: <original STUB summary kept as TL;DR>
## Problem
What category of human need does this pattern address? 2-3 paragraphs.
Concrete shape (control-loops example):
> Distributed systems drift. Nodes fail, network partitions heal, configs change underneath running services. Without a feedback mechanism, every drift event becomes an incident requiring human intervention. The control-loop pattern treats drift as the steady state and recovery as the loop body, not as exceptional handling.
## Principles
The timeless rules any implementation must follow. 3-5 sub-sections.
### Declarative desired state
The loop must read desired state from a stable source (CRD, config file, database row) — not infer it from observed state.
### Idempotent action
Each iteration's action must be safe to repeat. "Create resource" is wrong; "ensure resource exists" is right.
### Bounded blast radius
A single iteration mutates a small surface; convergence emerges from many iterations, not one heroic action.
## Trade-offs
Expand the original STUB trade-off into a table or grid. What axes do implementations vary along?
| Decision | Option A | Option B | Cost |
|---|---|---|---|
| Reconcile interval | tight (sub-second) | loose (minutes) | tight = noise + cost; loose = drift window |
| Trigger model | poll-based | event-based | poll = simple + lossy; event = fast + complex |
| Failure handling | retry-with-backoff | dead-letter | retry = self-healing; DLQ = visibility |
## Tools (as of YYYY-MM)
Current implementations with the date stamped (because tools age):
- **Kubernetes controllers** — reconcile via watch + work queue; the canonical example
- **Argo CD `Application` controller** — reconciles Git desired state against cluster actual state
- **Terraform `apply`** — non-continuous loop; you trigger each iteration manually
## Reading list
Books / papers / talks that landed for you while learning this pattern:
- "Kubernetes Patterns" (Bilgin Ibryam, 2023) — Chapter on the Operator pattern
- "Site Reliability Engineering" — the chapter on automation as an extension of the loop
## References
Where this pattern shows up across ROOT:
- Phase that first touched it: Year 1 Phase 7 (Kubernetes + GitOps)
- Other phases that revisit it: Year 2 Phase 11 (IaC), Year 3 Phase 18 (Streaming)
- Projects that exercise it: basecamp (every controller), terralabs (Crossplane providers)

By OUTLINE, you’ve LIVED through the phase that touches the pattern. The content is yours, not generic textbook prose.


DEEP shape (10-30 pages)

After 3+ months of operating something that depends on the pattern, you have war stories. Promote OUTLINE → DEEP.

---
title: "<Pattern Title>"
slug: <kebab-case>
status: DEEP ← changed from OUTLINE
category: <category>
canonical-implementations: [...]
last-deepened: YYYY-MM-DD ← updated
operated-since: YYYY-MM-DD ← added
---
# <Pattern Title>
> [TL;DR paragraph still at top]
## Problem
## Principles
## Trade-offs
## Tools
## Reading list
## Anti-patterns ← NEW at DEEP
Operational lessons from real incidents — what you've seen go wrong + why.
| Anti-pattern | Why it fails | What to do instead |
|---|---|---|
| Reconciling on every webhook event | Amplifies controller load under burst traffic | Coalesce events into a work queue with rate-limited dequeue |
| Storing observed state in the same place as desired state | Loop reads its own writes; convergence stalls | Separate the source of truth from the cache |
| Loop with unbounded retry | A poison resource can starve all others | Bounded retry + dead-letter visibility |
## What surprised me ← NEW at DEEP
Honest "I expected X, observed Y" entries from your weekly logs:
- "I expected Argo CD's resync interval to dominate cost; turned out the real cost was the diff calculation on large Apps."
- "I assumed reconcile loops were independent; learned the hard way that two controllers reconciling the same field race-condition each other."
## Compare ← NEW at DEEP
A second tool you used for the same pattern. The comparison forces you to articulate the *pattern* (not just the tool):
- Argo CD vs Flux for the same GitOps reconciliation
- Where each wins / loses (Argo's UI vs Flux's lighter footprint)
- What surprised me about the differences (the pattern is identical; the operator UX is what diverges)
## Operate ← NEW at DEEP
Operational depth — what running this in production for months taught you:
- The 3 most common alerts and what they actually mean (`ApplicationOutOfSync`, `ReconciliationLag`, `WebhookFailing`)
- The runbook path you most often follow (force-resync → check controller logs → check target cluster auth)
- The misconfigurations that cost you the most time (resource exclusions; incorrect `automated.prune` semantics)
## References: operational ← NEW at DEEP
Your own postmortems where this pattern broke (or held). These are *your* stories, not anyone else's.
- [postmortem 2026-W14] — Argo CD reconcile loop stuck on a CRD with a webhook that returned 500; the loop's bounded retry saved us from a cascade

DEEP is the pattern entry as a peer-reviewable artifact — the thing a hiring panel reads to verify your depth.


When to promote

Each pattern’s frontmatter has first-deepening: Year N Phase M — that’s the contract.

  • STUB → OUTLINE happens during the first phase that touches the pattern. The phase doc tells you which patterns it deepens (look at “Patterns deepened this phase” at the bottom of every phase doc).
  • OUTLINE → DEEP happens 3+ months after the phase that produced the OUTLINE, AND only if you’ve been operating something that depends on the pattern in those months. Premature DEEP is a lie to future-self.

Updating the depth-status table

patterns/index.md has a table at the bottom:

| STUB | 59 |
| OUTLINE | 0 |
| DEEP | 0 |

When you promote a pattern, you decrement one and increment the next. That’s the visible-progress dashboard for the library.


Anti-patterns

Anti-patternWhy
Pre-writing OUTLINE/DEEP without operating the patternGeneric textbook prose, not your understanding
Claiming DEEP for what’s actually OUTLINELies to future-self about real depth
Splitting STUB/OUTLINE/DEEP into separate filesCross-references break; URLs break
Forgetting to update the depth-status tableLose the visible progress dashboard
Writing the trade-off line genericallyThe trade-off is the load-bearing sentence; specific or skip
Letting AI draft past STUB without your operational hoursInflated depth corrupts the library’s signal

Cross-references