# Custom Timeouts (/sdks/kotlin/how-to/connection/custom-timeouts)



## Overview [#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 reconnection retries wait between attempts, how long an individual RPC blocks before giving up. 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. `ensureConnectedTimeoutMs` bounds how long the client waits for the initial connection; `pingIntervalSeconds` / `pingTimeoutSeconds` configure gRPC keep-alive probes that detect a stale connection before you try to use it; the `reconnection { }` DSL block's `initialBackoffMs` / `maxBackoffMs` / `multiplier` govern exponential backoff between reconnection attempts; and `unaryTimeoutMs` bounds individual unary RPCs like `ping()`. &#x2A;*Gotchas:** a `unaryTimeoutMs` shorter than the server's real processing time causes spurious failures, not faster detection of a genuinely broken call; an aggressive `pingIntervalSeconds` can flag a slow-but-healthy link as dead; and the `reconnection { }` backoff has no attempt cap by default, so it will keep retrying against a server that's down for good unless you bound it yourself.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000`
* Kotlin SDK installed (`implementation("io.kubemq.sdk:kubemq-sdk-kotlin:1.0.1")`)

## Code [#code]

```kotlin title="CustomTimeoutsExample.kt"
package io.kubemq.sdk.examples.connection

import io.kubemq.sdk.client.KubeMQClient
import kotlinx.coroutines.runBlocking

private const val ADDRESS = "localhost:50000"
private const val CLIENT_ID = "kotlin-connection-custom-timeouts"

fun main() = runBlocking {
    connectionTimeoutExample()
    keepAliveTimeoutsExample()
    reconnectionTimeoutExample()
    unaryTimeoutExample()
    println("Custom timeouts examples completed.")
}

private suspend fun connectionTimeoutExample() {
    println("=== Connection Timeout Configuration ===\n")

    // ensureConnectedTimeoutMs controls how long to wait for connection
    val client = KubeMQClient.queues {
        address = ADDRESS
        clientId = "$CLIENT_ID-conn-timeout"
        ensureConnectedTimeoutMs = 10_000 // 10 seconds
    }
    client.use {
        val info = it.ping()
        println("Connected with 10s connection timeout.")
        println("Server: ${info.host}\n")
    }
}

private suspend fun keepAliveTimeoutsExample() {
    println("=== Keep-Alive Timeout Configuration ===\n")

    val client = KubeMQClient.pubSub {
        address = ADDRESS
        clientId = "$CLIENT_ID-keepalive"
        keepAlive = true
        pingIntervalSeconds = 15
        pingTimeoutSeconds = 5
    }
    client.use {
        val info = it.ping()
        println("Connected with custom keep-alive:")
        println("  Ping Interval: 15 seconds")
        println("  Ping Timeout: 5 seconds")
        println("  Server: ${info.host}\n")
    }
}

private suspend fun reconnectionTimeoutExample() {
    println("=== Reconnection Interval Configuration ===\n")

    val client = KubeMQClient.cq {
        address = ADDRESS
        clientId = "$CLIENT_ID-reconnect"
        reconnection {
            initialBackoffMs = 2000
            maxBackoffMs = 60_000
            multiplier = 2.0
        }
    }
    client.use {
        val info = it.ping()
        println("Connected with 2s base reconnect interval.")
        println("  Backoff: 2s, 4s, 8s, 16s, ... up to 60s")
        println("  Server: ${info.host}\n")
    }
}

private suspend fun unaryTimeoutExample() {
    println("=== Unary Timeout Configuration ===\n")

    // unaryTimeoutMs controls timeout for unary gRPC calls
    val client = KubeMQClient.queues {
        address = ADDRESS
        clientId = "$CLIENT_ID-unary"
        unaryTimeoutMs = 30_000 // 30 seconds
    }
    client.use {
        val info = it.ping()
        println("Connected with 30s unary timeout.")
        println("Server: ${info.host}\n")
    }
}
```

## How It Works [#how-it-works]

* `ensureConnectedTimeoutMs` controls how long the client waits for the initial connection to be established.
* `pingIntervalSeconds` and `pingTimeoutSeconds` configure gRPC keep-alive probes.
* The `reconnection { }` DSL block configures exponential backoff: `initialBackoffMs`, `maxBackoffMs`, and `multiplier`.
* `unaryTimeoutMs` sets the deadline for individual unary gRPC calls (ping, send, etc.).

## Related [#related]

* [Connect](/sdks/kotlin/tutorials/connect)
* [Reconnection](/sdks/kotlin/how-to/error-handling/reconnection)
* [Kotlin SDK Reference](/sdks/kotlin/reference/client)
