go
74 lines · 1 tab
Leah Thompson
Jan 2026
1 tab
package realtime
import (
"fmt"
"net/http"
"time"
)
type Hub struct {
subscribe chan chan string
unsubscribe chan chan string
broadcast chan string
}
func NewHub() *Hub {
h := &Hub{subscribe: make(chan chan string), unsubscribe: make(chan chan string), broadcast: make(chan string, 128)}
go h.run()
return h
}
func (h *Hub) run() {
clients := map[chan string]struct{}{}
for {
select {
case c := <-h.subscribe:
clients[c] = struct{}{}
case c := <-h.unsubscribe:
delete(clients, c)
close(c)
case msg := <-h.broadcast:
for c := range clients {
select {
case c <- msg:
default:
}
}
}
}
}
func (h *Hub) ServeHTTP(w http.ResponseWriter, r *http.Request) {
flusher, ok := w.(http.Flusher)
if !ok {
http.Error(w, "streaming unsupported", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
ch := make(chan string, 16)
h.subscribe <- ch
defer func() { h.unsubscribe <- ch }()
heartbeat := time.NewTicker(15 * time.Second)
defer heartbeat.Stop()
for {
select {
case <-r.Context().Done():
return
case <-heartbeat.C:
fmt.Fprint(w, ": ping
")
flusher.Flush()
case msg := <-ch:
fmt.Fprintf(w, "data: %s
", msg)
flusher.Flush()
}
}
}
1 file · go
Explain with highlit
SSE is my go-to for “live updates” when I don’t need full bidirectional WebSockets. The key is to set the right headers (Content-Type: text/event-stream, Cache-Control: no-cache) and to flush periodically so intermediaries don’t buffer. I send heartbeats as : comments every ~15 seconds to keep load balancers happy and to detect dead clients. I also remove clients when r.Context().Done() fires, which prevents leaking channels and goroutines over time. The nice part is that SSE stays friendly to existing HTTP infrastructure and works well through proxies. In production I also cap the per-client buffer and drop slow consumers rather than letting them back up the whole broadcaster.
Related snips
go
package api
import (
"net/http"
"runtime/debug"
)
Expose build metadata for debugging deploys
go
observability
build
by Leah Thompson
1 tab
typescript
export interface RetryOptions {
retries: number;
baseMs: number;
maxMs: number;
signal?: AbortSignal;
onRetry?: (attempt: number, delay: number, err: unknown) => void;
Exponential backoff with jitter for retries
typescript
reliability
retry
by codesnips
2 tabs
go
package dbutil
import (
"context"
"github.com/jackc/pgconn"
Retry Postgres serialization failures with bounded attempts
go
postgres
transactions
by Leah Thompson
1 tab
go
package files
import (
"context"
"time"
Presigned S3 upload URLs (AWS SDK v2)
go
aws
s3
by Leah Thompson
1 tab
go
package deps
import (
"net"
"net/http"
"time"
HTTP client tuned for production: timeouts, transport, and connection reuse
go
http
client
by Leah Thompson
1 tab
go
package api
import (
"io"
"net/http"
"os"
Safe multipart uploads using temp files (bounded memory)
go
http
uploads
by Leah Thompson
1 tab
Share this code
Here's the card — post it anywhere.