KubeMQ
Client SDKsGoHow-to guidesConnection

Custom Timeouts

Configure connection and per-operation timeouts on the KubeMQ Go client to tune latency and failure behavior.

Overview

Every client operation has an implicit deadline — how long to wait for the initial connection, how long before a dead socket is detected, how long a single RPC blocks before giving up, how long Close() waits for in-flight work to drain. The defaults are reasonable for a healthy local network, but they're wrong for high-latency links, connections that pass through load balancers or NAT gateways, or servers that occasionally run slow under load. Tuning timeouts explicitly is how you trade fast-fail behavior against tolerance for transient slowness.

Each timeout targets a different phase of the client lifecycle. WithConnectionTimeout bounds the initial dial; WithKeepaliveTime / WithKeepaliveTimeout configure gRPC HTTP/2 keepalive pings that detect a stale connection before you try to use it; WithDrainTimeout bounds how long Close() waits for outstanding calls to finish before it forces the transport shut. Gotchas: a connection timeout shorter than your network's real handshake latency causes spurious startup failures, not faster detection of a genuinely down server; keepalive pings set too aggressively can flag a slow-but-healthy link as dead; and raising WithMaxReceiveMessageSize / WithMaxSendMessageSize only helps if the server's own limits are raised to match — otherwise you've just moved the failure from client to server.

Prerequisites

  • KubeMQ server running on localhost:50000
  • Go SDK installed (go get github.com/kubemq-io/kubemq-go/v2)

Code

main.go
// Example: connection/custom-timeouts
//
// Demonstrates how to configure custom timeouts for the KubeMQ client
// including connection timeout, keepalive, and drain timeout.
//
// Channel: go-connection.custom-timeouts
// Client ID: go-connection-custom-timeouts-client
//
// Run with a KubeMQ server on localhost:50000
// (see https://docs.kubemq.io/deploy).
package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/kubemq-io/kubemq-go/v2"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	// Create a client with custom timeout configuration.
	client, err := kubemq.NewClient(ctx,
		kubemq.WithAddress("localhost", 50000),
		kubemq.WithClientId("go-connection-custom-timeouts-client"),
		// Custom connection timeout (default: 10s)
		kubemq.WithConnectionTimeout(15*time.Second),
		// Custom keepalive settings (default: 10s interval, 5s timeout)
		kubemq.WithKeepaliveTime(30*time.Second),
		kubemq.WithKeepaliveTimeout(10*time.Second),
		// Custom drain timeout for Close() (default: 5s)
		kubemq.WithDrainTimeout(10*time.Second),
		// Max message sizes
		kubemq.WithMaxReceiveMessageSize(50*1024*1024), // 50 MB
		kubemq.WithMaxSendMessageSize(50*1024*1024),    // 50 MB
	)
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}
	defer client.Close()

	info, err := client.Ping(ctx)
	if err != nil {
		log.Fatalf("Ping failed: %v", err)
	}
	fmt.Printf("Connected with custom timeouts: host=%s version=%s\n",
		info.Host, info.Version)
}

How It Works

  1. WithConnectionTimeout(15 * time.Second) caps the initial gRPC dial; if the server does not respond within this window, NewClient returns an error.
  2. WithKeepaliveTime and WithKeepaliveTimeout configure gRPC HTTP/2 keepalive pings — useful for detecting stale connections through NATs or load balancers that silently drop idle TCP flows.
  3. WithDrainTimeout(10 * time.Second) sets the budget for client.Close() to finish in-flight operations before forcibly closing the transport.
  4. WithMaxReceiveMessageSize / WithMaxSendMessageSize override gRPC's default 4 MB limit; increase these only when you know your payloads are large — oversized limits waste memory on every RPC.

Was this page helpful?

On this page