ws-reconnect

February 15, 2026 ยท View on GitHub

Go Reference Go Report Card License: MIT Coverage

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, and OnError.
  • ๐Ÿ”’ 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:

OptionDefaultDescription
WithBackoff(BackoffConfig)Initial: 500ms, Max: 30s, Multiplier: 1.5, Jitter: trueExponential backoff configuration for retries
WithPingInterval(duration)30sInterval between sending outbound ping frames
WithPongWait(duration)60sMaximum duration to wait for a pong response
WithWriteWait(duration)10sMaximum deadline allowed to write a message
WithHeaders(http.Header)emptyCustom HTTP headers sent during WebSocket handshake
WithSubprotocols(strings...)emptyWebSocket subprotocols requested from server
WithBufferSize(read, write)4096, 4096Input and output I/O buffer sizes in bytes
WithWriteChanSize(size)256Capacity 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.