Single-node · In-memory · gRPC

Heads up: I ended up switching to NATS + PostgreSQL. If you need consumer groups, bare NATS won't help — you need JetStream, which requires persistence. tinybroker fills the gap when you want in-memory consumer groups with no persistence overhead. The code works and is free to use; just know why you're reaching for it.

k3s / Kubernetes sidecar

In a small k3s cluster or a single-namespace Kubernetes deployment, tinybroker fits naturally as a lightweight coordination bus between your application replicas. It deploys as a single-replica Deployment (or as a sidecar) and exposes a ClusterIP service — no persistent volumes, no StatefulSet, no operator.

Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: tinybroker
spec:
  replicas: 1
  selector:
    matchLabels:
      app: tinybroker
  template:
    metadata:
      labels:
        app: tinybroker
    spec:
      containers:
        - name: tinybroker
          image: phughk/tinybroker:latest
          ports:
            - containerPort: 50051
            - containerPort: 8080
            - containerPort: 9090
          readinessProbe:
            httpGet:
              path: /ready
              port: 8080
            initialDelaySeconds: 2
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
          resources:
            requests:
              cpu: 10m
              memory: 16Mi
            limits:
              cpu: 500m
              memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
  name: tinybroker
spec:
  selector:
    app: tinybroker
  ports:
    - name: grpc
      port: 50051
    - name: health
      port: 8080
    - name: metrics
      port: 9090

Connecting from app pods

Use tinybroker.your-namespace.svc.cluster.local:50051 as the broker address. In most frameworks this is an environment variable:

env:
  - name: BROKER_ADDR
    value: "tinybroker.default.svc.cluster.local:50051"

Prometheus scraping

Add annotations to have Prometheus auto-discover the metrics endpoint:

metadata:
  annotations:
    prometheus.io/scrape: "true"
    prometheus.io/port:   "9090"
    prometheus.io/path:   "/metrics"

Restart behaviour

tinybroker is in-memory. A pod restart clears all subscriptions and buffered messages. If your application pods restart simultaneously (rolling update), they will re-subscribe on startup. Design your startup sequence to subscribe before publishing to avoid dropped messages during the brief reconnect window.

When NOT to use this pattern

If you need the broker to survive independent of your application pods — or if a broker restart would cause data loss you cannot tolerate — use a stateful broker (NATS JetStream, Kafka, etc.) instead.