MIT·zero dependencies·Go 1.21·since 2017

Your Go service is one panic() away from a full restart.Ergo makes it one process.

Ergo is a Go framework for distributed systems. Every process gets a supervisor, an address and a mailbox — so the one that fails dies and comes back, and the rest never notice. Clustering included, compiled into your binary.

No broker. No sidecar. No codegen. No dependencies.

Read the docs →
MyNode@localhost                 up 00:04:12
├── myapp                        running
│   └── mysup       one_for_one
│       ├── worker#1  4,102 msg
│       └── worker#2  4,097 msg
└── radar                          :9090

worker#1  terminated: panic
mysup     restarting worker#1 …

│       ├── worker#1     6 msg   ← back
│       └── worker#2  4,131 msg   ← never noticed

node uptime unchanged. no redeploy. no page.

In plain Go that panic ends the process — and you cannot recover it if the goroutine came from a library you do not own.

Trusted in production

ITxPTpublic transport
Platform Engineeringdevops
Samsung Adsad tech
Gcorecloud & edge
Kasperskycybersecurity
3Commasfintech
Lilith Gamesgaming
ByteDancetechnology
“Suddenly I want a wrapper around each goroutine that bubbles up the panic to the main thread without crashing the app — that sounds a lot like an erlang supervision tree.”

— Hacker News, July 2024

He was not talking about Ergo. He did not know it existed. He had hit the wall every Go service hits eventually and reasoned his way to the shape of the answer.

That shape has been shipping for years.

The whole thing, web UI included, has a dependency graph of zero.

Not “few”. Not “carefully audited”. Ergo’s go.sum is an empty file — and so is the observer’s, a cluster inspector with an embedded browser UI and an agent interface, built entirely on the standard library. No cgo either.

// ergo.services/ergo — go.mod, complete file
module ergo.services/ergo

go 1.21
  • Static binary, one full node11.6 MB
  • Embedded observer UI280 KB
  • Bytes in go.sum0
google.golang.org/grpc42 modules
go.temporal.io/sdk25 modules
ergo.services/ergo0
observer — UI + agents0

Counted with go list -m all. The Prometheus, OTLP and etcd integrations do carry their vendors’ graphs — they are separate modules you opt into, not something you inherit.

Nothing to CVE-scan. Nothing to upgrade. Nothing to take to your security team.

You have state that has to live somewhere.

So it goes in Redis, and now every read is a network hop and a cache-invalidation bug. Or it stays in memory and you spend a quarter on sticky sessions, consistent hashing and a StatefulSet — and it still evaporates on the next rolling update.

// any node in the cluster, same call
process.Send(
    gen.ProcessID{
        Name: "session",
        Node: "edge-7@eu",
    },
    MessageJoin{Room: "lobby"},
)

One Send. Whether that process sits in this binary or three datacenters away is decided inside the function, not by you.

The state stays in the process, and the process has a name. There is no cache to invalidate and no affinity to configure, because there is nothing to route to except the thing itself.

When it dies, its supervisor decides what happens next — restart just it, restart its siblings with it, or give up and let the failure travel one level out. Four supervision types, four restart strategies, declared in a struct and changeable while the node runs.

Every observability tool shows an agent the platform your code runs on.

This one shows it your code. Ergo speaks MCP: 38 tools and 13 resource lenses over a live cluster. The interesting one asks a running process what it knows — and the process answers, because answering is a callback, not an export.

 process_state order-worker · prod-7

  config.workers      8
  config.timeout      30s
  stats.processed     3944
  stats.errors        46
  stats.rate          17/s
  runtime.uptime      3m51s

No metric was exported. No dashboard was configured six months ago. The process was asked.

Prometheus can only show what you decided to record before you knew what would go wrong. Here the agent reads the live variable — and it discovers what it may ask, because the process describes its own surface first.

Mailboxes report depth and the age in nanoseconds of the oldest unprocessed message, which is the difference between “this service is slow” and “this service is merely behind”.

And the objection you are already forming, answered structurally: 26 of the 38 tools cannot change anything, a permission ceiling can only ever narrow, and on a node built with DisableManage the rest are not denied the process they address is never started.

Tests that start fifty real nodes inside one go test.

The harness calls the same node.Start production calls, binds real listeners and speaks the real wire protocol; only discovery is swapped for something in-memory. There is no Docker anywhere in the tree and no container runtime in your CI.

21M+ msg/seclocally
5.5M msg/secover the network
2.57 KBper process, at one million
2.9M msg/secto 1M subscribers, 10 nodes

Throughput on a 64-core processor, memory on an Apple M4 Max. Full captures in the benchmarks repo, reproducible with go test -bench=.

The last one is the figure that matters: reaching a million subscribers costs ten network messages — one per node, not one per subscriber. That is the broker you did not deploy.

The boring half of a cluster is already written.

Twenty modules on one import path, all of them MIT. There is no licence boundary, no feature matrix, and nothing here to buy.

framework

ergo — processes, supervisors, applications, the wire format, clustering, tracing, cron, the test harness

MIT
operate

observer cluster inspector, web UI and agent interface · health K8s probes · metrics Prometheus · pulse OTLP · radar both on one port

MIT
cluster

grid distributed registry and process groups · leader Raft leader election · etcd registrar for small and medium clusters

MIT
speak to

websocket · sse · erlang EPMD, handshake, DIST and ETF, so a Go node can join a BEAM cluster

MIT
past ~70 nodes

Saturn — the central registrar. Every node re-registers once a second, which stops paying off at scale; Saturn is built for the other side of that line.

MIT

No key, no phone-home, no node cap, no tier that unlocks the useful part. Saturn, the registrar for large clusters, was the one component under a commercial licence and moved to MIT in 3.3.

Being built on top of it

ergo.observer

The cluster inspector as a hosted service — the same surface you already run locally, without running it yourself.

October 2026
ergo.engineer

Design the system into a machine-readable architecture contract, hand it to your coding agent over MCP, then investigate incidents against what the system was meant to do rather than against its telemetry.

December 2026
ergo.cloud

One transparent network for your nodes, across data centres, clouds and continents. No VPN, no proxy, no tunnels.

waitlist

What people build with it.

The same primitives, pointed at different problems. Each line is the part of the framework that does the work.

Microservices

Actor-per-request, supervision trees for fault isolation, distributed service discovery

Real-time systems

21M+ msg/sec throughput, four priority queues, sub-millisecond mailbox latency tracking

IoT backends

TCP/UDP meta processes, Port for device protocols, distributed pub/sub for sensor data fanout

Financial systems

Guaranteed message delivery, distributed consensus with built-in leader election, no external dependencies

Gaming servers

Lightweight actors, worker pools, WebSocket support, cluster-wide event broadcasting

Edge computing

Small binary footprint, NAT traversal, the observer's MCP endpoint reachable through the cluster proxy without opening a port

Where it does not fit.

  • No durable execution. Ergo does not persist state. A restarted process starts clean; it does not resume mid-computation. If you need workflows that survive a crash you want Temporal — and it runs perfectly well on Ergo nodes.
  • Not a log. Cluster pub/sub replaces a broker used for fanout. It does not replace retention, replay, or a consumer group rewinding a week.
  • Back-pressure, not magic. A full mailbox returns an error you have to handle, and a remote send is fire-and-forget unless you mark it important.
  • Go, not polyglot. A Python service talks to it over HTTP like anything else — or you write that one in Erlang and it joins the cluster directly.
  • No hot code reload. New code means restarting the node.

Three commands, then open the observer.

$ go install ergo.tools/ergo@latest
$ ergo init MyNode github.com/you/mynode
$ go run ./cmd
 http://localhost:9911
Read the docs →