April 3, 2026
3m 37s

In one embedded product that I worked on, all sensor data was aggregated into a single, ever-growing structure in shared memory. Every thread read from it, and multiple sensor threads wrote to it. Shared memory synchronization was handled with handwritten code.
For a small number of sensors, this seemed fine. We had one place for the “current state of the world.” (For the record, I was skeptical from the start.)
But the system was intended to be highly customizable. Different customers required different sensor configurations on top of the default set.
Every new sensor requirement meant modifying that shared structure, updating the threads that used it, and adding more synchronization. The system became highly coupled, difficult to reason about, and increasingly error-prone.
Over time, we ended up with a great example of what I call “Coral Reef Software”: accreted layers of structure that were risky to change. Some parts were well-written, maybe even elegant at times (like some parts of a reef). But overall, the result was something that was a danger to navigation if we weren’t very careful.
In contrast, I think about a well-structured system as an archipelago: a cluster of islands related by geography. A software system can be thought of in the same way.
Each island represents a bounded component with a clear responsibility. Communication between the islands is explicit and controlled, not implicit through shared state.
Value objects moving through queues are like trade between islands. Information flows between components, but the components themselves remain independent. No shared state crosses these boundaries.
In a real archipelago, movement between islands is not arbitrary. Ships don’t anchor wherever they like. They enter through ports: designated, controlled points of entry where traffic is visible, constrained, and managed.
That maps directly to software systems.
In an archipelago-style design, components don’t interact through shared state or ad hoc calls. They communicate through well-defined interfaces: queues, message boundaries, or APIs that act as ports. Data enters and leaves at specific points, and the flow between components is explicit.
This makes behavior visible. You can see where data is coming from, where it is going, and where it might accumulate under load. Backpressure becomes a property of the system, not an emergent side effect.
In a real system, each “island” is a bounded component with clear ownership, often aligned with a thread or execution context.
Communication between islands happens through “trade routes” in the form of thread-safe queues.
“Goods” move through the queues as value types.
No shared state crosses these boundaries. Threads do not share objects, they exchange values.
In the system described earlier, this kind of structure would have avoided the central shared state entirely. Instead of multiple threads reading and writing to a single structure, each component would publish values through well-defined interfaces, making data flow explicit and reducing coupling as the system scaled.
In the system described earlier, data arrived in bursts and was pushed through an event-driven pipeline layered on top of an OS abstraction. Execution paths were implicit, and contention only became visible under load.
An archipelago-style approach would have made that behavior explicit. Each processing stage would be connected through bounded queues; clear points of entry and exit where data ownership and flow are visible. Instead of work being scheduled implicitly through threads and callbacks, the movement of data between stages would define execution.
This would have made failure modes easier to reason about. Queue depth would expose where work was accumulating. Backpressure would appear at well-defined boundaries instead of emerging unpredictably inside the system. Latency would be tied to identifiable stages, not hidden interactions between threads.
It also would have simplified porting. The structure of the system (stages, queues, and flow) would remain intact, with platform differences reduced to mapping those constructs onto OS primitives. Instead of expanding an abstraction layer, the work becomes preserving an explicit design.
Coral reef software isn’t usually the result of one bad decision. It’s the result of many small, reasonable decisions made without a clear model of the system as a whole.
Coral reef software grows by accretion. Archipelago architecture grows by composition.
If you can’t clearly trace how data moves through your system, you don’t have an architecture, and someone is going to lose a boat.