oss

Rich Hickey's simplest architecture test: what did you braid together?

8 sources 5 primary sources July 24, 2026

Text
Rich Hickey standing at a lectern beside a projected slide titled Chunked Sequences at a 2009 software event.

Clojure creator Rich Hickey speaking in June 2009, two years before the Strange Loop talk annotated here. Photograph by Howard Lewis Ship.[8]

Video mode

This article includes 1 embedded video.

  1. 1 Rich Hickey explains how separating concerns makes software easier to understand and change YouTube embed

Software teams often call a system “simple” when its setup is quick, its syntax is familiar, or its demo fits on one screen. Those qualities can be valuable, but they say little about what happens when the system must change. A one-command tool can still bind storage, policy, timing, and failure handling so tightly that every revision becomes a coordinated migration.

Rich Hickey's 2011 Strange Loop talk Simple Made Easy supplies a sharper vocabulary. “Easy” describes nearness: what a person already knows or can reach quickly. “Simple” describes structure: whether concerns remain separate or have been braided together. The official conference page frames the talk as an argument for robust, flexible software built from composable parts; InfoQ's contemporaneous notes preserve its sequence and timestamps.[1][2][3]

The talk is worth revisiting because its best idea is not “use Clojure.” It is a review method that works before a team chooses a language or framework. Watch for three moves: Hickey splits one vague adjective into two axes; he names common forms of entanglement; then he turns abstraction into a set of questions about what, who, how, when, where, and why. The useful result is a way to inspect change coupling—not a leaderboard of programming paradigms.

Image context: the lead photograph shows Hickey speaking in June 2009, two years before the 2011 Strange Loop talk.[2][8]

At 2:30, two axes replace one vague adjective

Hickey's opening distinction is most useful when treated as an operational glossary, not as a contest over dictionary definitions. Ease belongs to a relationship between a tool and a person: installation, familiarity, documentation, local availability. Simplicity belongs to the artifact: how many independent jobs have been interleaved inside it.[1][3] Something can therefore be easy but complex, or unfamiliar but structurally simple.

That separation improves technical review because it prevents one benefit from impersonating another. “Everyone knows this framework” is a legitimate staffing and delivery argument. It is not evidence that the framework produces boundaries that can change independently. Conversely, a small algebra or immutable data model may impose an initial learning cost while reducing the number of facts needed to reason about later behavior. A team should price both dimensions rather than use “simple” to conceal the trade.

There is a concrete test. List the changes the system expects: alter a validation rule, replace a database, replay an event, move work to a queue, add a second client, or revise retry policy. Then ask which other decisions must move with each change. If a policy revision forces edits to transport, persistence, scheduling, and presentation, the problem is not merely that the code is large. Those concerns have been braided. The review target is not the fewest components; it is the fewest forced joint changes.

Around 28:50, the list is a provocation—not a scorecard

The talk's central table places state, objects, methods, inheritance, imperative loops, actors, and object-relational mapping on the complex side, while placing values, functions, namespaces, data, protocols, queues, and declarative systems on the simpler side.[1][3] Read literally, this can sound like a universal ban on mainstream constructs. Read as a searchlight, it is stronger: each item asks which dimensions a construct tends to join.

An object can combine identity, current value, and behavior. A method can combine a function with hidden state and a namespace. An imperative loop can combine the result being computed with the exact order used to compute it. None of those combinations guarantees a bad program. They do enlarge the unit that must be understood and changed together. The relevant question is whether that coupling expresses the problem itself or merely the chosen implementation.

Hickey's language design makes the preference concrete. Clojure was built as a hosted Lisp for the JVM, with immutable persistent data structures and explicit facilities for controlled change.[4] Its state model distinguishes an identity from the value currently associated with that identity: values do not mutate in place, while references manage the transition from one value to another.[5] Protocols similarly name a set of operations separately from any one implementation and can be extended without requiring a class hierarchy.[6]

Those mechanisms do not erase complexity. Persistent structures consume resources; reference types carry concurrency semantics; protocols can be extended carelessly; the JVM and outside services keep their own clocks and failure modes. Their architectural contribution is narrower and more defensible: they make some joints visible. The value can travel and be inspected without dragging a mutable identity with it. An abstraction can be discussed without selecting its implementation. Change still exists, but it has an address.

At 35:40, state reveals the hidden clock

The talk's most durable diagnostic is that mutable state joins value with time. Reading a field no longer answers only “what is this?” It also raises “when was this observed?”, “who could change it?”, and “what else had to be consistent at that moment?”[1][3] A module boundary does not remove those questions if callers retain shared access to the same changing location.

This matters far beyond functional-language debates. A deployment manifest whose tag can be overwritten, a cache entry with an implicit expiry, a database row updated in place, and a feature flag read at different moments all combine information with a clock. The team may need that state; most useful systems do. The design choice is whether history and coordination are implicit side effects or explicit parts of the model.

Moseley and Marks made a related independent argument in Out of the Tar Pit: state and explicit control are major sources of accidental complexity, so essential state should be separated from logic and from performance-oriented control.[7] That does not mean putting every change on an event bus. It means preserving stable values where possible, isolating the small set of identities that truly change, and giving transitions named operations with observable failure behavior.

For a small service, this might be an immutable request value passed through pure validation and calculation before one repository call changes durable state. For a larger platform, it might mean versioned configuration, append-only facts, idempotency keys, and a queue boundary that keeps scheduling out of domain logic. The operational maturity requirement rises with the machinery. If a team cannot monitor lag, replay safely, or govern schemas, introducing a distributed log in the name of “simplicity” merely moves the braid into operations.

From 49:17, abstraction becomes six review questions

In the closing section, Hickey organizes design around what, who, how, when, where, and why.[1][3] The sequence is useful because architecture discussions often begin with “how”—a framework, database, or deployment target—before the team has isolated the other dimensions.

Start with what: the capability and invariants, expressed without an implementation. Identify who: the values or entities involved, without making each one carry every behavior. Defer how to replaceable implementations behind the named capability. Treat when and where as scheduling and placement decisions rather than smuggling them into business functions. Keep why—policy—from dissolving into scattered conditionals.

This is not a demand for six services or six interface files. Separation is semantic before it is physical. A single process can preserve these boundaries, and a fleet of microservices can violate all of them through shared schemas, synchronous call chains, and coordinated releases. The test is whether a reader can explain one dimension without reconstructing the others, and whether a team can change it without negotiating a system-wide rewrite.

That is why Simple Made Easy remains valuable after its tool references have aged. Its vocabulary turns an aesthetic preference into a falsifiable question: which decisions are forced to move together? Familiarity can be improved with learning and tooling. Necessary complexity can be documented and contained. But once unrelated concerns are braided into one artifact, neither a shorter syntax nor a faster scaffold makes them independent. The simplest useful move is to find the braid before adding another strand.

Sources

  1. Strange Loop Conference, “Simple Made Easy — Rich Hickey” (2011) — embedded conference talk.
  2. Strange Loop, “Simple Made Easy” — official 2011 session page and speaker provenance.
  3. InfoQ, “Simple Made Easy” — independent presentation summary, key takeaways, and timestamped show notes.
  4. Clojure, “Rationale” — official account of the language's JVM hosting model, immutable persistent data structures, and approach to concurrency.
  5. Clojure, “Values and Change: Clojure's approach to Identity and State” — official explanation of immutable values, identities, references, and controlled transitions.
  6. Clojure, “Protocols” — official reference for separating named abstractions from implementations and extending types without inheritance.
  7. Ben Moseley and Peter Marks, “Out of the Tar Pit” (2006) — independent analysis of state, control, and accidental complexity.
  8. Howard Lewis Ship, “Rich Hickey” (3 June 2009), Wikimedia Commons — source page for the lead photograph.
Previous GitLab's 2017 database loss turned a staging snapshot into the recovery plan

Recommended In oss

Matched by subject and format