Files
Ryan Hamamura 60009124c9
Some checks failed
CI / Build and Test (push) Has been cancelled
feat: add declarative Options.Streams for automatic JetStream stream creation
Streams listed in Options.Streams are created by Start() when the
embedded NATS server initializes, replacing manual EnsureStream calls
during setup. Migrates nats-chatroom and pubsub-crud examples.
2026-02-19 12:24:44 -10:00

3.3 KiB

NATS Chatroom Example (Embedded)

A chatroom built with Via and an embedded NATS server, demonstrating pub/sub messaging as an alternative to the custom Rooms implementation in ../chatroom.

Via includes an embedded NATS server that starts automatically — no external server required.

Key Differences from Original Chatroom

Aspect Original (../chatroom) This Example
Pub/sub Custom Rooms struct (~160 lines) NATS subjects
Member tracking Manual map[TU]Syncable NATS handles subscribers
Publish timing Ticker every 100ms + dirty flag Instant delivery
Durability None (in-memory) JetStream persists to disk
Multi-instance Not supported Works across server instances
External deps None None (NATS embedded in binary)

Run the Example

go run ./internal/examples/nats-chatroom

That's it. No separate NATS server needed.

Open multiple browser tabs at http://localhost:7331 to see messages broadcast across all clients.

Architecture

┌─────────────────────────────────────────────────────────┐
│                    Single Binary                         │
│                                                          │
│  Browser A          Embedded NATS         Browser B      │
│      │                   │                    │          │
│      │-- Via Action ---> │                    │          │
│      │   (Send msg)      │                    │          │
│      │                   │                    │          │
│      │              nc.Publish()              │          │
│      │              "chat.room.Go"            │          │
│      │                   │                    │          │
│      │<-- Subscribe -----|---- Subscribe --->│          │
│      │    callback       │    callback        │          │
│      │                   │                    │          │
│      │-- c.Sync() ------>│<--- c.Sync() -----|          │
│      │   (SSE)           │     (SSE)          │          │
│                                                          │
└─────────────────────────────────────────────────────────┘

JetStream Durability

Messages persist to disk via JetStream. Streams are declared in Options.Streams and created automatically when v.Start() initializes the embedded NATS server:

v.Config(via.Options{
    Streams: []via.StreamConfig{{
        Name:     "CHAT",
        Subjects: []string{"chat.>"},
        MaxMsgs:  1000,
        MaxAge:   24 * time.Hour,
    }},
})

Stop and restart the app - chat history survives.

Code Comparison

Original chatroom - 160+ lines of custom pub/sub:

  • Rooms struct with named rooms
  • Room with member tracking, mutex, dirty flag
  • Ticker-based publish loop
  • Manual join/leave channels

This example - ~60 lines of NATS integration:

  • via.Subscribe(c, subject, handler) for receiving
  • via.Publish(c, subject, data) for sending
  • Streams declared in Options — NATS handles delivery, no polling