# Exponential Backoff for Reconnections in wacli: Implementation and Usage

> Discover wacli's exponential backoff for reconnections. Learn how it increases delays between attempts, respects bounds, and handles context cancellation for robust connectivity.

- Repository: [Peter Steinberger/wacli](https://github.com/steipete/wacli)
- Tags: internals
- Published: 2026-04-17

---

**wacli uses an exponential backoff strategy in `ReconnectWithBackoff` to gradually increase delay times between reconnection attempts, respecting minimum and maximum bounds while checking for context cancellation.**

The **steipete/wacli** repository implements a robust reconnection mechanism for WhatsApp Web clients that avoids aggressive retry loops. This article examines the **exponential backoff for reconnections** logic found in the source code, explaining how the algorithm balances reliability with resource efficiency.

## How wacli Implements Exponential Backoff

The core reconnection logic resides in [`internal/wa/client.go`](https://github.com/steipete/wacli/blob/main/internal/wa/client.go). The `Client` struct provides the `ReconnectWithBackoff` method, which orchestrates the retry loop with configurable delay parameters.

### The ReconnectWithBackoff Method

Located at lines 52-71 in [`internal/wa/client.go`](https://github.com/steipete/wacli/blob/main/internal/wa/client.go), this method accepts a context and duration bounds, then executes a controlled retry loop:

```go
func (c *Client) ReconnectWithBackoff(ctx context.Context, minDelay, maxDelay time.Duration) error {
    delay := minDelay
    for {
        if ctx.Err() != nil {
            return ctx.Err()
        }
        if err := c.Connect(ctx, ConnectOptions{AllowQR: false}); err == nil {
            return nil
        }
        select {
        case <-ctx.Done():
            return ctx.Err()
        case <-time.After(delay):
        }
        delay *= 2
        if delay > maxDelay {
            delay = maxDelay
        }
    }
}

```

The algorithm follows this sequence:

1. **Initialize delay** to `minDelay`.
2. **Check context cancellation** before each attempt using `ctx.Err()`.
3. **Attempt connection** via `c.Connect` with `AllowQR: false` to prevent new QR code generation during reconnection.
4. **Wait for the current delay** using `time.After(delay)` within a select block that also monitors context cancellation.
5. **Double the delay** for the next iteration (`delay *= 2`).
6. **Clamp to maximum** if the doubled value exceeds `maxDelay`.

## Integration with the Sync Engine

The sync subsystem in [`internal/app/sync.go`](https://github.com/steipete/wacli/blob/main/internal/app/sync.go) demonstrates practical application of the backoff logic. The `App.reconnect` method wraps the core functionality with additional timeout controls.

### Practical Usage in App.reconnect

At lines 21-32 in [`internal/app/sync.go`](https://github.com/steipete/wacli/blob/main/internal/app/sync.go), the method invokes the backoff with specific timing constraints:

```go
func (a *App) reconnect(ctx context.Context) error {
    rctx := ctx
    if a.maxReconnect > 0 {
        var cancel context.CancelFunc
        rctx, cancel = context.WithTimeout(ctx, a.maxReconnect)
        defer cancel()
    }
    
    return a.wa.ReconnectWithBackoff(rctx, 2*time.Second, 30*time.Second)
}

```

This implementation:

- Uses a **minimum delay of 2 seconds** to avoid immediate retry storms.
- Sets a **maximum delay of 30 seconds** to ensure reconnection attempts occur at least every half minute.
- Optionally applies an overall timeout via `maxReconnect` flag, creating a deadline context that terminates the backoff loop after the specified duration.

## Complete Usage Example

When building applications with wacli, you can implement custom reconnection logic using the exposed method. The following example demonstrates a five-minute reconnection window with custom delay bounds:

```go
package main

import (
    "context"
    "log"
    "time"
    
    "github.com/steipete/wacli/internal/wa"
)

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
    defer cancel()
    
    client := wa.NewClient()
    
    // Exponential backoff: start at 1s, cap at 10s
    if err := client.ReconnectWithBackoff(ctx, 1*time.Second, 10*time.Second); err != nil {
        log.Fatalf("reconnection failed: %v", err)
    }
    
    log.Println("successfully reconnected")
}

```

This pattern mirrors the implementation in [`internal/app/sync.go`](https://github.com/steipete/wacli/blob/main/internal/app/sync.go), allowing you to adjust `minDelay`, `maxDelay`, or the parent context duration based on your infrastructure requirements.

## Summary

- **wacli implements exponential backoff** via `ReconnectWithBackoff` in [`internal/wa/client.go`](https://github.com/steipete/wacli/blob/main/internal/wa/client.go) to prevent aggressive reconnection attempts.
- The algorithm **doubles the delay** after each failed attempt, clamping at a configurable maximum while respecting context cancellation.
- **Default timing** uses 2-second minimum and 30-second maximum delays as configured in [`internal/app/sync.go`](https://github.com/steipete/wacli/blob/main/internal/app/sync.go).
- The method integrates with Go's **context package** to support timeout and cancellation propagation throughout the reconnection lifecycle.

## Frequently Asked Questions

### What is exponential backoff?

**Exponential backoff** is a retry strategy that progressively increases the wait time between consecutive failed operations. In wacli, this means each reconnection attempt waits twice as long as the previous one, starting from `minDelay` and capping at `maxDelay`. This approach reduces server load and network congestion during outages.

### How does wacli handle context cancellation during reconnection?

The `ReconnectWithBackoff` function checks `ctx.Err()` at the start of each loop iteration and includes a `select` statement that monitors `ctx.Done()` during the delay phase. If the context is cancelled or times out, the function immediately returns the context error, terminating the backoff loop without further connection attempts.

### What are the default delay values in wacli?

According to the implementation in [`internal/app/sync.go`](https://github.com/steipete/wacli/blob/main/internal/app/sync.go), the default **minimum delay is 2 seconds** and the **maximum delay is 30 seconds**. These values provide a reasonable balance between quick reconnection during transient failures and conservative backoff during extended outages.

### Can I customize the backoff parameters?

Yes, the `ReconnectWithBackoff` method exposes `minDelay` and `maxDelay` as parameters, allowing you to specify custom durations based on your use case. Additionally, you can control the overall reconnection timeout by wrapping the context with `context.WithTimeout` before passing it to the method, as demonstrated in the sync engine implementation.