It's NUTS: a live website with Symfony, NATS and NUTS
(nats, symfony, php) 1 min read by Bartosz Pachołek
A real-time price ticker where NATS is the only backend service: work queue, key-value store and live event bus at once.
It's NUTS: build a dynamic website using Symfony, NATS and NUTS walks through a real-time price ticker, and its code is on GitHub as nut-exchange. The interesting part is what is not there: no database, no Redis and no separate message broker.
NATS plays three roles
| role | NATS feature | used by |
|---|---|---|
| work queue | INGEST stream |
Symfony Messenger |
| last-value store | nutprices KV bucket |
the worker writes, the home page reads |
| live event bus | EVENTS stream |
NUTS, to the browser |
How a price travels
POST /api/ticks -> Messenger -> INGEST stream
|
NutTickHandler (worker)
KV "nutprices" publish events.prices
|
GET / -> KV snapshot NUTS -> EventSource('/events?topic=prices')
The page renders the current prices straight from the KV bucket, then subscribes over SSE and applies live changes.
Safe against duplicates
The handler combines a timestamp guard (never overwrite a newer value) with revision-based compare-and-set on the KV bucket, so duplicate or out-of-order deliveries and concurrent writers are safe. The JetStream publish carries a message id for stream-level deduplication.
FrankenPHP embeds PHP in Caddy and NUTS is a Caddy module, so the whole stack is one web process plus one worker.