ws-reconnect
February 15, 2026 ยท View on GitHub
ws-reconnect is a lightweight, resilient, and production-ready WebSocket client for Go. It wraps gorilla/websocket with seamless automatic reconnection, exponential backoff with jitter, heartbeat management (ping/pong), and lifecycle callbacks.
Features
- ๐ Automatic Reconnection: Seamlessly reconnects upon network failures or server disconnects.
- โฑ๏ธ Exponential Backoff & Jitter: Prevents the thundering herd problem using customizable retry intervals with randomized jitter.
- ๐ Built-in Heartbeat: Automatic Ping/Pong frames with configurable read/write deadlines.
- ๐ช Rich Lifecycle Hooks: Event callbacks for
OnConnect,OnDisconnect,OnTextMessage,OnBinaryMessage, andOnError. - ๐ Thread-Safe Writing: Non-blocking asynchronous message dispatch (
SendText,SendBinary,SendJSON) with dedicated write buffers. - ๐ Graceful Shutdown: Context-aware cancellation and clean close handshakes.
- ๐งช Heavily Tested: Comprehensive unit test suite with >93% coverage and zero race conditions (
-race).
Installation
go get github.com/sing198/ws-reconnect
Quick Start
package main
import (
"context"
"log"
"time"
wsreconnect "github.com/sing198/ws-reconnect"
)
func main() {
client := wsreconnect.New(
"wss://echo.websocket.org",
wsreconnect.WithPingInterval(20*time.Second),
wsreconnect.WithOnConnect(func() {
log.Println("Connected to WebSocket server!")
}),
wsreconnect.WithOnDisconnect(func(err error) {
log.Printf("Disconnected: %v (reconnecting...)", err)
}),
wsreconnect.WithOnTextMessage(func(msg []byte) {
log.Printf("Received message: %s", string(msg))
}),
wsreconnect.WithOnError(func(err error) {
log.Printf("Error: %v", err)
}),
)
defer client.Close()
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := client.Connect(ctx); err != nil {
log.Fatalf("Connection failed: %v", err)
}
// Send message thread-safely
_ = client.SendText("Hello, WebSocket!")
// Send structured JSON data
_ = client.SendJSON(map[string]string{"type": "greeting", "user": "alice"})
time.Sleep(5 * time.Second)
}
Configuration Options
Use the functional options pattern to customize client behavior:
| Option | Default | Description |
|---|---|---|
WithBackoff(BackoffConfig) | Initial: 500ms, Max: 30s, Multiplier: 1.5, Jitter: true | Exponential backoff configuration for retries |
WithPingInterval(duration) | 30s | Interval between sending outbound ping frames |
WithPongWait(duration) | 60s | Maximum duration to wait for a pong response |
WithWriteWait(duration) | 10s | Maximum deadline allowed to write a message |
WithHeaders(http.Header) | empty | Custom HTTP headers sent during WebSocket handshake |
WithSubprotocols(strings...) | empty | WebSocket subprotocols requested from server |
WithBufferSize(read, write) | 4096, 4096 | Input and output I/O buffer sizes in bytes |
WithWriteChanSize(size) | 256 | Capacity of the outbound message queue |
Customizing Backoff
client := wsreconnect.New(
"wss://api.example.com/ws",
wsreconnect.WithBackoff(wsreconnect.BackoffConfig{
InitialInterval: 200 * time.Millisecond,
MaxInterval: 10 * time.Second,
Multiplier: 2.0,
Jitter: true,
MaxRetries: 5, // 0 for unlimited retries
}),
)
Running the Example
A complete runnable echo demo is included in the example/ folder:
go run ./example/main.go
Running Tests
All tests are verified with the Go race detector and coverage profiling:
go test -v -race -coverprofile=coverage.out ./...
go tool cover -func=coverage.out
License
This project is licensed under the MIT License.