Akagitsune banner — cyberpunk cityscape with crimson glow
Akagitsune logo

Akagitsune

赤狐

A generic realtime WebSocket gateway built in Rust.Pure transport — it relays, it does not interpret.

1M/s
Deliveries sustained
6ms
Worst p99 at 1M/s
100%
Delivered at 1M/s
View on GitHub

What It Is

A WebSocket relay that stays out of your way

Akagitsune is a generic realtime gateway — a piece of infrastructure, not a product. It connects sockets and moves bytes. What those bytes mean is entirely your decision.

Payload-Agnostic

The gateway forwards your data without touching it. Chat messages, game states, live dashboards, IoT telemetry — it all rides the same wire. The meaning is yours; the transport is ours.

Real-Time, Always

Built on asynchronous Rust with a lock-free hot path. Every message is serialized once — not once per receiver — then broadcast to all connected peers instantly.

Backpressure Over Breakage

When a slow client falls behind, Akagitsune drops its queued messages and warns it — rather than slowing down everyone else. The fast stay fast; the slow get a second chance.

Three Tasks, One Connection

Each connection runs a reader (ingest), a bridge (fanout), and a writer (flush). Bounded queues everywhere, no shared locks, reference-counted message clones. Clean, predictable, debuggable.

Get it running

$ cargo run
# Connect at ws://127.0.0.1:3000/ws

Performance

One million, sustained

The target is a million deliveries a second inside a 1020 ms p99 budget. All three traffic shapes clear it, and clear half again as much. Past that they part ways: fanout is the expensive one, and it breaks first.

Service p99 against offered load

Log scale, because the spread runs from 3 ms to 825 ms. The dashed rule is the 20 ms budget; the tinted band above it is out of spec.

  • ingestmany senders, one topic
  • mesheveryone talks to everyone
  • fanoutone sender, every socket

Ingest stops at 1.5M because it was never run above it. The hollow marker at 2.78M is a separate exploratory shape, and the only point where delivery rather than latency is what gives out.

Every run, in full

Latency in milliseconds. Rows that miss the budget are dimmed. Scroll the table sideways for the rest of the columns.

Benchmark runs by offered load and traffic shape, with p50 and p99 service latency, delivery rate, and whether each run stayed inside the 20 ms budget.
Offered loadShapeConnsp50p99DeliveredAgainst budget
1,000,000ingest1011.833.00100%within budget
1,000,000mesh2013.065.39100%within budget
1,000,000fanout5012.466.03100%within budget
1,500,000ingest1011.663.16100%within budget
1,500,000mesh2513.536.51100%within budget
1,500,000fanout5016.1618.88100%within budget
2,000,000mesh20116.4548.77100%over budget
2,000,000fanout100142.88193.02100%over budget
2,782,322explore301180.74825.3492.74%delivery breaks

Every number is from a single local run on Apple M4 Pro, 14 cores, release build, gateway and load generator on the same machine — not a production deployment. Latency is service latency: message arrival minus actual send, the more conservative of the two figures the harness records. The highest load every shape held inside the budget was 1,500,000 deliveries a second. Benchmark scripts and methodology are in the repository.

Protocol

Simple by design

No handshake, no auth negotiation, no subscription dance. Connect, receive your ID, start sending. Four frame types cover everything.

On connect, the server immediately sends a welcome frame with the client's assigned UUID. No handshake required — you're in.

// Server → Client (on connect)
{
"type": "welcome",
"id": "a3f1b2c4-5678-..."
}

Scope

Sharp boundaries, clear purpose

The scope test is simple: a feature belongs in the gateway only if it can be implemented without knowing what the payload means. Everything else belongs in your application.

In the gateway

  • Connection management & lifecycle
  • Message relay & envelope framing
  • Backpressure & queue overflow handling
  • Topic / room-based routing (planned)
  • Per-connection rate limiting (planned)
  • Auth & admission control (planned)
  • Delivery semantics & acknowledgements
  • Multi-instance backplane (planned)

In your app

  • Usernames, profiles, or identity
  • Message content interpretation
  • Chat history or persistence
  • Business logic or domain rules
  • Push notifications beyond WebSocket
  • REST API endpoints for data

"If it needs to know what the message says, it doesn't belong here."

The Operatives

Four tasks, four faces

Every connection in Akagitsune runs three concurrent tasks — reader, bridge, and writer — plus a lead that ties them together. Meet the cast.

Roadmap

What comes next

Akagitsune is under active development. These are the features on the horizon — all of them pass the scope test.

Topic & Room Routing

Next

Replace the single broadcast bus with a topic-based subscription model. Clients subscribe to rooms; messages route only to subscribers — eliminating O(N²) fanout.

Authentication

Planned

Token-based admission control at connection time. The gateway verifies identity without interpreting payload — auth is transport-level, not content-level.

Per-Connection Rate Limiting

Planned

Configurable ingest rate limits per connection to prevent abuse and smooth traffic spikes. Token bucket or sliding window, decided at the transport layer.

Multi-Instance Backplane

Planned

Horizontal scaling via a shared backplane (Redis, NATS, or a custom protocol) so multiple gateway instances form a single logical relay.

Delivery Acknowledgements

Exploring

Optional per-message ack/nack for clients that need delivery guarantees. Still payload-agnostic — the gateway confirms transport, not meaning.