How MessageFoundry fits together
Explore the components, process boundaries, message flow, and interface wiring below. For the detailed reference, read ARCHITECTURE.md.
MessageFoundry started in May 2026 and is in Early Access. Read the project status →
Top-level components
The system includes operator tools, configuration, service commands, test tools, and a migration tee relay. Operator tools connect to the engine through its local API.
System topology
The engine runs as a service. Separate client processes connect only through its localhost API. The API depends on the engine; the engine never imports the API or a client.
The durable staged queue
The engine acknowledges receipt after it commits the message to the ingress stage, before routing, transforms, or delivery. Each handoff uses one committed transaction. The stored stages support retries and replay without a separate broker.
The engine commits each message before acknowledgment and each stage handoff in one transaction. After a crash, it can repeat the last step without skipping it. Normal operation delivers each message once. A crash after a downstream send, but before recording success, can cause that message to be sent again. This is at-least-once delivery. A repeated HL7 message keeps the same MSH-10 control ID, so the downstream system can detect and remove duplicates.
On anonymized, representative traffic, one inbound interface measured ~50 messages/second on commodity hardware. That is about 180,000 in a peak hour, or roughly 1.6 million a day under the traffic pattern below. The engine stores each message before acknowledgment and delivers in strict first-in, first-out order per interface.
Daily estimates account for uneven traffic. In de-identified ADT traffic from a live hospital feed, the busiest hour was roughly 2.7× the daily average. Messages averaged 11.5 KB, giving about 18 GB/day at that estimated volume. Message sizes vary by feed. Base64-encoded documents or images can greatly increase storage and bandwidth needs. Scale by splitting feeds at the source across interfaces, with an optional multi-node tier. Total capacity does not grow as a simple sum of single-interface rates. Measure your transforms, storage, and hardware. Read the throughput measurements → · Throughput & capacity (PDF) ↓
Connections, Routers, and Handlers — wired by name
Configuration links components by name. An inbound Connection names a Router, which selects Handlers. Each Handler sends to outbound Connections. There is no enclosing channel object. Use guided wizards or write the configuration in Python.
Reuse components by name
Define each component once, then reference its name wherever you need it.
- Reuse a named destination, transform, or router across interfaces without copying its definition.
- Add a destination with another Send, or reroute a feed by changing a name. Review those changes in version control.
- Configuration checks reject unknown routers, missing handlers, duplicate names, and duplicate ports.
- Test each Router or Handler as a separate function. Teams or AI agents can work on independent parts in parallel.
See it run for yourself
Follow the quickstart to route a test message, or read the feature list and engine documentation.