Ursula — Distributed Event Stream Servers tool screenshot
Distributed Event Stream Servers

Ursula: Best Event Stream Servers for Dev Teams in 2026

8 min read·

Ursula turns append-only event timelines into a quorum-replicated HTTP and SSE service with sub-50 ms P99 appends and S3-backed cold storage.

Pricing

Open-Source

Tech Stack

Rust, axum, HTTP, SSE, Raft, gRPC, S3

Target

dev teams building document editors, agent runtimes, workflows, and chat apps

Category

Distributed Event Stream Servers

What Is Ursula?

Ursula is a distributed event stream server from Tonbo for replayable, append-only timelines behind document edits, agent runs, workflows, and chat. Ursula is one of the best Event Stream Servers tools for dev teams building document editors, agent runtimes, workflows, and chat apps, and the project page reports 35.2k appends/sec on a 3-node EC2 quorum with 6.1 ms p99 SSE fan-out to 1,000 subscribers. It speaks the Durable Streams Protocol over plain HTTP and SSE, so browsers, mobile clients, and serverless workers can read, write, and tail the same timeline without a broker SDK.

The core sell is not generic message brokering. Ursula keeps event streams outside the broker network, uses Raft for quorum durability, and pushes older committed chunks to S3 for cold storage economics. That makes it a better fit than broker-shaped systems when the unit of data is an ordered timeline that must survive node loss and remain directly addressable over the public internet.

Quick Overview

AttributeDetails
TypeDistributed Event Stream Servers
Best Fordev teams building document editors, agent runtimes, workflows, and chat apps
Language/StackRust, axum, HTTP, SSE, Raft, gRPC, S3
LicenseApache 2.0
GitHub StarsN/A on the scraped page
PricingOpen-Source
Last Releasev0.1.x prototype — date not listed

Ursula is still in the prototype phase, but the design is already opinionated: thread-per-core execution, independent Raft groups, HTTP-native writes, and S3-backed cold tiering. The project page shows a working quickstart, a cluster architecture, and benchmark numbers, which is enough to evaluate fit before investing in an integration.

Who Should Use Ursula?

  • Platform teams building collaborative products that need ordered event timelines for documents, comments, agent traces, or chat history.
  • Backend engineers shipping browser-first or mobile-first APIs that want plain HTTP and SSE instead of a private broker protocol.
  • Infra teams running self-hosted systems that need quorum durability, node-failure tolerance, and predictable storage economics on standard S3.
  • Indie hackers and startup CTOs who want a durable stream layer without adopting Kafka-style operational overhead.

Not ideal for:

  • Teams that need a mature connector ecosystem, stream processing jobs, and a decade of operational tooling out of the box.
  • Workloads that require cross-stream transactions, because Ursula explicitly keeps groups independent and avoids a cross-group commit path.
  • Teams that want a fully packaged SaaS or a polished client SDK layer today, because the project still lists client SDKs as roadmap work.

Key Features of Ursula

  • HTTP-native event timelines — Ursula exposes streams through plain HTTP and SSE, which means a browser, a mobile app, or a serverless worker can append and tail the same stream without a broker-specific transport. The project page shows direct curl examples for bucket creation, stream creation, appends, and live tailing.
  • Quorum-replicated durability — writes are leader-serialized inside a Raft group and acknowledged only after a majority of replicas persist and apply the command. That gives you acknowledged-write survival across a single node failure, which is the minimum bar for durable timelines.
  • Thread-per-core, multi-Raft layout — each stream hashes to one Raft group and one owner core, so hot-path state stays disjoint and avoids shared mutable contention. This is the right shape for predictable latency under concurrency because each core owns its own set of groups.
  • Hot ring plus cold tier — appends commit into an in-memory ring and Raft log first, then background flushers move older committed chunks to S3. That design keeps write latency low while preserving plain S3 economics for long-lived history.
  • Stateless HTTP front dooraxum handles parsing, routing, and response rendering, while mutable stream state stays inside the owning group actor. That keeps the edge simple and reduces the amount of state that can drift across request handlers.
  • Independent group failure domains — each group has its own Raft instance, log, state machine, watchers, and flush budget. A failure or backlog in one group does not automatically cascade into every other timeline.
  • Live fan-out for subscribers — the project benchmark reports SSE fan-out to 1,000 subscribers at 6.1 ms p99, which is the number that matters for chat feeds, editor cursors, and agent event streams. If you need tracing around those numbers, pair Ursula with OpenTrace for end-to-end latency visibility.

Ursula vs Alternatives

ToolBest ForKey DifferentiatorPricing
UrsulaHTTP-native durable event timelinesRaft-replicated, S3-backed append-only streams over HTTP and SSEOpen-Source
KafkaLarge-scale event pipelines and stream processingHuge ecosystem, connectors, and mature ops toolingOpen-Source / Enterprise
NATS JetStreamLightweight pub/sub with persistenceSimple broker operations and subject-based routingOpen-Source
ElectricSQLLocal-first sync and replicationClient database sync around Postgres, not a standalone stream serverOpen-Source

Pick Kafka when you need connector depth, stream processing, and an established enterprise operating model. Kafka is still the safer choice for teams that want a generic broker backbone rather than a stream primitive shaped around timelines.

Pick NATS JetStream when the primary problem is low-latency pub/sub with persistence and a small operational footprint. It is better for message-oriented systems than for timeline storage that must be directly readable over HTTP.

Pick ElectricSQL when your application wants local-first data sync and a database-oriented replication model. Ursula is the more direct fit when the API contract itself is an append-only stream, especially for editors, workflows, and agents. If you are automating rollout and observability around this kind of cluster, djevops and OpenTrace are sensible adjacent tools.

How Ursula Works

Ursula is built around a simple rule: one stream belongs to one Raft group, and that group is owned by a deterministic core on every node. The system uses shared-nothing execution, so each core owns disjoint groups and avoids a global lock or a cross-group transaction path. That is a better fit for append-heavy timelines than a broker architecture that spreads state across a generic message fabric.

The write path is split into a hot tier and a cold tier. Appends land in an in-memory ring and the Raft log first, then background flushers export older committed chunks to S3. Reads and tails stay HTTP-native, and the same stream can be fetched by offset or followed live over SSE, which is what makes Ursula usable from browsers and serverless code without special clients.

cargo run --bin ursula -- --listen 127.0.0.1:4437 --core-count 3 --raft-group-count 3 --wal-dir ./wal --raft-log-dir ./raft
curl -X PUT http://127.0.0.1:4437/demo
curl -X PUT http://127.0.0.1:4437/demo/hello
curl -X POST http://127.0.0.1:4437/demo/hello -H 'Content-Type: application/octet-stream' --data-binary 'hello world'
curl 'http://127.0.0.1:4437/demo/hello?offset=-1'

The first command starts a local cluster-style node with persistent directories for the WAL and Raft log. The curl calls create a bucket, create a stream, append bytes, and read the latest item back. If you want live delivery, add live=sse and tail the stream as the server emits event: data frames.

Pros and Cons of Ursula

Pros:

  • Direct HTTP and SSE access means application code can write and tail streams with standard tooling instead of a private client stack.
  • Quorum durability protects acknowledged writes from a single node loss, which is the minimum viable safety property for shared timelines.
  • Predictable hot-path latency comes from thread-per-core execution and disjoint Raft groups, which reduces lock contention under concurrent load.
  • S3 cold storage economics keep long-lived history cheap without forcing a special storage tier.
  • Benchmark-backed throughput is already visible on the project page, including 35.2k appends/sec and 6.1 ms p99 fan-out on the reported EC2 setup.
  • Protocol clarity is high because the server implements the Durable Streams Protocol rather than inventing another proprietary API shape.

Cons:

  • The project is still a prototype in the v0.1.x line, so some operational pieces are not finished yet.
  • No dynamic membership today means clusters are static, which is a real constraint for teams that expect rolling membership changes.
  • Backup and restore tooling is missing, so total-cluster recovery from S3 is not a supported turnkey path yet.
  • Client SDKs are not shipped yet, so most integrations will start from raw HTTP and SSE calls.
  • No cross-group transactions means you should not treat Ursula like a general-purpose database or a multi-stream ACID system.
  • Source build is the current path because pre-built binaries are still listed as forthcoming.

Getting Started with Ursula

cargo run --bin ursula

curl -X PUT http://127.0.0.1:4437/demo
curl -X PUT http://127.0.0.1:4437/demo/hello
curl -X POST http://127.0.0.1:4437/demo/hello -H 'Content-Type: application/octet-stream' --data-binary 'hello world'
curl -N 'http://127.0.0.1:4437/demo/hello?offset=-1&live=sse'

That starts a single in-memory node on 127.0.0.1:4437, which is enough for local evaluation and protocol testing. If you need persistence, switch to --wal-dir and --raft-log-dir; if you need a cluster, the project docs walk through multi-node deployment and S3 configuration. The important point is that Ursula is usable from day one with the same HTTP verbs your app already knows.

Verdict

Ursula is the strongest option for self-hosted durable event timelines when you need HTTP-native writes, SSE tailing, and Raft durability without Kafka-style broker overhead. Its best strength is the split between hot in-memory rings and S3 cold storage, but the current prototype still lacks dynamic membership and shipped SDKs. Recommended if you own the infrastructure and want timeline primitives, not a general broker.

Frequently Asked Questions

Looking for alternatives?

Compare Ursula with other Distributed Event Stream Servers tools.

See Alternatives →

You Might Also Like