explaingit

aasheeshlikepanner/vase

0GoAudience · developerComplexity · 4/5ActiveSetup · moderate

TLDR

Go pub/sub message broker that uses a lock-free ring buffer and per-subscriber cursors to claim much higher throughput than Redis Pub/Sub at high fan-out.

Mindmap

mindmap
  root((vase))
    Inputs
      Publisher messages
      Subscriber connections
      WAL segment files
    Outputs
      Fanned-out messages
      Durable log
      CRC32 checksums
    Use Cases
      Fan out live updates
      Replace Redis Pub/Sub
      Study lock-free design
    Tech Stack
      Go
      TCP
      mmap
      Goroutines

Things people build with this

USE CASE 1

Run a single-node pub/sub broker for live updates or chat fan-out with many subscribers

USE CASE 2

Replace Redis Pub/Sub in benchmarks where throughput collapses past dozens of subscribers

USE CASE 3

Study a working lock-free ring buffer with padded cursors and a memory-mapped WAL

USE CASE 4

Build a service on the custom binary protocol over TCP using one goroutine per connection

Tech stack

GoTCPmmap

Getting it running

Difficulty · moderate Time to first run · 30min

Single node only with no replication, and slow subscribers are dropped, so plan for in-process testing first.

In plain English

Vase is a publish/subscribe message broker written in Go. A pub/sub broker is the middle piece in a system where one program (the publisher) wants to send the same message to many other programs (the subscribers) at the same time, for things like live updates or chat fan-out. The README pitches Vase as a faster alternative to Redis Pub/Sub for cases with many subscribers, claiming 62 times the throughput at 100 subscribers in the author's benchmark. The author starts by explaining why Redis slows down. Redis Pub/Sub runs in a single thread that loops over every subscriber on each publish call, so throughput scales as O(n) in the subscriber count. Their measurements show Redis dropping from 38,000 messages per second with one subscriber to 1,800 with one hundred. Vase takes a different approach: the publisher writes a message once into a shared ring buffer, and each subscriber holds its own cursor and reads from the buffer independently. That makes the publish step O(1) regardless of how many readers are listening. The ring buffer is lock-free. A publisher does one atomic increment to claim a slot, writes the message, and marks the slot ready with a sequence number. Each subscriber compares its cursor against that sequence number to know when a new message is available. The buffer uses power-of-two capacity so indexing can use a bitwise AND instead of a modulo, and each cursor is padded to a full 64-byte cache line so that one subscriber's writes do not invalidate another's cached state. For durability, Vase has an optional write-ahead log. Every message is appended to a memory-mapped 128MB segment file with a CRC32 checksum before it is treated as published. On restart, the log is scanned, checksums are verified, and playback resumes from the last valid offset. The broker speaks a small custom binary protocol over TCP, one goroutine per connection, with batching of up to 64 messages per flush. The README is upfront about limits: single node only, no replication, slow subscribers get disconnected, and end-to-end publish rate still touches the network serialization layer.

Copy-paste prompts

Prompt 1
Build vase from source, start the broker, and run the included benchmark with 100 subscribers
Prompt 2
Walk me through how the lock-free ring buffer in vase claims slots and signals readiness to readers
Prompt 3
Add a client library in Python that speaks the vase binary protocol and can subscribe to a topic
Prompt 4
Extend the write-ahead log to support segment rotation and bounded retention
Prompt 5
Add metrics for slow-subscriber disconnects and expose them on a Prometheus endpoint
Open on GitHub → Explain another repo

Generated 2026-05-22 · Model: sonnet-4-6 · Verify against the repo before relying on details.