Research

Independent engineering projects, run alongside client work.

Projects on problems I keep coming back to: keeping architectural intent intact as AI accelerates delivery, communication that holds up when infrastructure can't be trusted, the smallest useful shape for a staged message system, whether the operational discipline that runs a reactor plant transfers to software, and whether identity can be made portable and self-owned without a central authority. Each exists to find out whether an approach actually helps — by building it and using it on real problems.

Meridian

An open question: does making architectural intent explicit actually help teams hold onto it once AI is writing most of the code?

As AI generates more code, the risk shifts from “can we produce code?” to “does the code still respect the architecture we intended?” Architectural intent tends to scatter across documents, diagrams, ADRs, tickets, chat, code, and individual memory, and becomes hard to hold onto during delivery. That much I have seen repeatedly.

Meridian is a prototype I have been building to test one possible answer: capture the architecture context and constraints, surface the decisions that actually need consensus, record them with their rationale, and check later changes against that baseline. The real question is whether that is genuinely useful or just more process.

I use it on real architecture problems — my own, and a few offered by people who deal with the same thing — to find out where it helps and where it does not. It is early, and any decisions it surfaces stay with the people accountable for them.

If you are wrestling with the same problem, I would be glad to compare notes. Get in touch about the research →

1M5

Resilient, infrastructure-independent communications.

A long-running personal engineering project (since 2018): a serverless peer-to-peer messaging system with no central infrastructure, built to keep working when central services, specific network paths, or identity assumptions can't be trusted or aren't available.

I designed and built the architecture and much of the implementation in Java/Android/JavaFX: peer discovery over interchangeable transports (I2P, Tor, direct), hardware-backed OpenPGP identities, graceful degradation as network conditions change, and an integrated Bitcoin/Lightning value-transfer layer. The through-line is redundancy and decentralization — no single network, service, or intermediary that failure or interference can take down.

Open source. It has produced working prototypes and a substantial body of architecture and systems engineering in an area I care about: communication that survives infrastructure denial.

Get in touch about 1M5 →

SEDA bus

A long-standing question: what is the smallest useful broker-less staged message system, and does one design survive very different runtimes?

Staged event-driven architecture — decomposing a system into stages connected by bounded queues, each with its own admission control — is an old idea I keep returning to. Message buses are a crowded space; the interesting question is the minimal one: the smallest broker-less, in-process kernel that still gives you back-pressure, routing, retry, and observability, with the adaptive load-tuning left as a known next step.

I have built the same design in seven runtimes with deliberately different concurrency models: Rust (a shared thread pool, zero dependencies), Java (on the JVM, with optional guaranteed-delivery persistence), Python (built to exercise free-threaded CPython, where staged CPU-bound work finally runs in parallel across cores), TypeScript / Node (the event loop for I/O stages, worker threads for CPU stages), C++ (header-only, real OS threads, no garbage collector — the closest mechanical translation of the Rust model), C# (the CLR's managed thread pool and Task-based async), and Go (goroutines and channels — arguably the most natural home for a staged, queue-connected design, since the runtime's own concurrency primitives are built around exactly that shape). Writing it seven times is the point — it shows what each runtime's model does to the design, and where “the same” stops being the same.

A small, on-and-off effort, not a product. None of the seven implements SEDA's original adaptive controller — the part that retunes resources from measured load at runtime — which is the piece that would make the name fully earned.

service-bus — lifecycle management and discovery layered over a seda-bus — exists in the same seven ports. seda-bus-compare measures the bus in isolation, with a deliberately near-zero-cost consumer; service-bus-compare asks a different question, wiring each port's own ra-common hashcash proof-of-work implementation in as a real, identical, CPU-bound unit of work and measuring end-to-end throughput at a single consumer, ten independent consumers, and ten consumers each fed by a dedicated producer. That third configuration turned out to matter: it caught a flat result for Rust that looked like a real concurrency limit but was actually this benchmark's own single-producer design bottlenecking a language fast enough to expose it — and, separately, that TypeScript's flat result under load was the harness never exercising Node's real worker_threads capability, not a ceiling in the language itself.

seda-bus: the full design and the seven implementations, with benchmark results for each →
service-bus: the service layer built on top of it, with the real-workload benchmark →
The repositories are on GitHub →

Rickover

An open question: does the operational discipline that keeps a reactor plant safe transfer to software, or is software's failure domain too different?

Before software I spent nine years operating naval nuclear reactors. That program has run since 1955 with no reactor accident, and the reason is a culture with named, teachable parts: casualty procedures with a hard line between the actions you do from memory and the ones you do with the page open; qualification before you stand the watch; drills on a schedule; a blameless critique after every one. Software operations has picked up incident commanders and postmortems, but not the rehearsed-response part.

Rickover is a small experiment in importing it: writing failure responses as casualty procedures in a fixed structure, drilling them under a clock with the fault optionally injected for real, and producing an after-action review every time so readiness is measurable.

The honest counter-case is that it may not transfer. A reactor plant has bounded, well-known failure modes and changes rarely; a distributed system has open-ended failure modes and changes every deploy. If the analogy breaks it probably breaks on failure-mode enumeration and on procedures going stale faster than they can be drilled. Part of the project is finding out how badly. Open source, early.

get in touch about the research →

DID

An open question: the cryptography for self-owned identity has been settled for years. Why has almost nobody adopted it — and what closes the gap?

Nearly every identity people use is issued: by a platform, a provider, a CA. It can be suspended, correlated across services, or lost when the issuer goes away. Self-sovereign identity says the identifier should be derived from keys the holder controls, with trust built from signed vouches rather than handed down. W3C DIDs had a decade to make that work and OpenPGP had thirty years; both were technically sound and neither reached ordinary people. Nostr is the first thing in the space that has actually moved — because the key is the identity, and people received one as a side effect of a social app they already wanted.

So the open question shifted. It isn't whether the model works — it's why adoption keeps failing, and where a central authority sneaks back in anyway. Two places, it turns out: key loss (lose the private key and the identity and every vouch is gone, with no reset), and verification (Nostr's common check, NIP-05, resolves a name through DNS, which puts a registrar and a certificate authority back in the trust path).

DID is the identity and key-management service I built for 1M5, where identity has to keep working under denied and degraded network conditions. The working implementation is built on OpenPGP key rings, and the honest finding is that that ecosystem's weight — heavy keys, awkward distribution, a trust model few people operated — is most of what makes self-sovereign identity feel impractical. The direction now is not another system but the two missing pieces of the one that has users: social recovery — a threshold of guardians you choose co-sign a move to a new key, so your friends are your recovery — and attestations that replace the DNS domain with N people you already trust. Both are plain signed events; W3C DID interoperability stays as a thin compatibility view and nothing more.

The deliverable is a short specification and a small library, published before any product and in TypeScript first — where the client developers who would adopt it actually work. Open source, early. If you are building on decentralized identity, or comparing notes on the move from OpenPGP to Nostr-era primitives, get in touch about the research →

Why this work

The research and the client work feed each other.

These projects come out of patterns seen repeatedly in 25 years of architecture work, and nine before that operating naval reactors — architectural intent that doesn't survive delivery, systems that assume infrastructure that isn't always there, load that overwhelms a service before anyone notices, and failure responses nobody has rehearsed. Building them end-to-end keeps the thinking concrete and the hands in current stacks.

Smaller experiments, prototypes, and libraries live on GitHub at github.com/resolvingarchitecture.