Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

Go-client configuration reference

This page documents every configurable option in clickhouse-go v2.x. For a guide with code examples, see Configuration.

How options are set

Options exist at three scopes:

Scope How to set Lifetime
Connection clickhouse.Options struct or DSN string All queries on the connection
Query clickhouse.Context() with WithXxx functions Single query execution
Batch PrepareBatch() option functions Single batch operation

Where scopes overlap, the more specific scope wins: Batch > Query > Connection. For Settings, query-level keys are merged with connection-level keys and query-level wins on conflict.

Via Options struct:

conn, err := clickhouse.Open(&clickhouse.Options{
    Addr:        []string{"localhost:9000"},
    Auth:        clickhouse.Auth{Database: "default", Username: "default", Password: ""},
    DialTimeout: 10 * time.Second,
    Compression: &clickhouse.Compression{Method: clickhouse.CompressionLZ4},
})

Via DSN string:

db, err := sql.Open("clickhouse", "clickhouse://user:pass@localhost:9000/default?dial_timeout=10s&compress=lz4")

Via Connector (database/sql with Options struct):

db := sql.OpenDB(clickhouse.Connector(&clickhouse.Options{
    Addr:        []string{"localhost:9000"},
    Auth:        clickhouse.Auth{Database: "default", Username: "default"},
    DialTimeout: 10 * time.Second,
}))
// Set database/sql-only pool settings after creation
db.SetConnMaxIdleTime(5 * time.Minute)

Via context (per-query):

ctx := clickhouse.Context(context.Background(),
    clickhouse.WithQueryID("my-query-123"),
    clickhouse.WithSettings(clickhouse.Settings{"max_execution_time": 60}),
)
rows, err := conn.Query(ctx, "SELECT ...")

Connection options

Protocol and connection

Option Type Default DSN param Description Best practice When misconfigured
Protocol Protocol (int) Native Scheme: clickhouse://=Native, http://=HTTP Communication protocol: Native (0) for TCP, HTTP (1) for HTTP Use Native for ~30% better performance. Use HTTP for proxy support, firewall traversal (port 80/443), or HTTP-only compression (gzip/br). See TCP vs HTTP. HTTP scheme with Native port (9000): connection refused. Native blocked by firewall: timeouts.
Addr []string ["localhost:9000"] (Native) ["localhost:8123"] (HTTP) Comma-separated hosts in URL List of "host:port" addresses for connection and failover Specify multiple addresses in production for HA. Correct ports: 9000 (Native), 8123 (HTTP), 9440 (Native+TLS), 8443 (HTTP+TLS). Single address: no failover. Wrong port: "connection refused". Empty/nil: defaults to localhost, fails in distributed deployments.
ConnOpenStrategy ConnOpenStrategy (uint8) ConnOpenInOrder (0) connection_open_strategy (in_order, round_robin, random) Strategy for selecting a server from Addr. InOrder (0)=failover, RoundRobin (1)=load balance, Random (2)=random. InOrder for active-standby. RoundRobin for active-active/K8s. Random to avoid thundering herd. InOrder with active-active: first server gets all load, others idle. All strategies try all servers on failure – only affects which is tried first.

Authentication

Option Type Default DSN param Description Best practice When misconfigured
Auth.Username string "default" username or URL user portion Username for ClickHouse authentication Never use default in production. Create dedicated users with minimal permissions. Wrong username: "Code: 516. DB::Exception: Authentication failed". Empty string: silently uses "default".
Auth.Password string "" password or URL password portion Password for ClickHouse authentication Use env vars or secret managers in production. URL-encode special characters in DSN. Wrong password: "Code: 516. DB::Exception: Authentication failed". Special chars not URL-encoded: parsing errors.
Auth.Database string "" (server default) database or URL path (/mydb) Default database for the connection Always specify explicitly. Use dedicated databases per application in production. Non-existent: "Code: 81. DB::Exception: Database xyz doesn't exist". Empty in multi-tenant setup: queries hit wrong database.
GetJWT func(ctx) (string, error) nil (programmatic only) Callback returning JWT for ClickHouse Cloud auth. Overridable per query with WithJWT(token). (Since v2.35.0) Implement token caching/refresh - called per connection/request. Expired token: auth errors. Blocking callback: timeouts. JWT takes precedence over user/pass. Requires TLS - without it, falls back to user/pass silently.
GetJWT: func(ctx context.Context) (string, error) {
    return getTokenFromVault(ctx)
}

Timeouts

Option Type Default DSN param Description Best practice When misconfigured
DialTimeout time.Duration 30s dial_timeout Max time to establish a new connection. Also controls pool acquisition wait when MaxOpenConns is reached. 5-10s on LAN, 15-30s on WAN/cloud, 1-2m if connecting to an idled ClickHouse Cloud service. Never below 1s. Too short: "clickhouse: acquire conn timeout" during congestion, or connection failure before an idled Cloud service finishes waking. Too long (> 60s): app hangs during outages.
ReadTimeout time.Duration 5m (300s) read_timeout Max time to wait for a server response per read call. Applied per block, not entire query. Context deadline takes precedence. 10-30s for short interactive queries; 5-30m for long analytical queries. Too short: "i/o timeout" or "read: connection reset by peer" mid-query; server continues executing. Too long: dead connections not detected.

Connection pool

Option Type Default DSN param API Description Best practice When misconfigured
MaxIdleConns int 5 max_idle_conns Both Max idle (unused but alive) connections in pool 50-80% of expected concurrent queries. Low: 2-5, medium: 10-20, high: 20-50. Too low: connection churn, higher latency. Too high: wasted memory. Capped at MaxOpenConns automatically.
MaxOpenConns int MaxIdleConns + 5 (default: 10) max_open_conns Both Max total connections (idle + active) Low: 10-20, medium: 20-50, high: 50-100. Formula: concurrent queries + burst + buffer. Monitor: SELECT * FROM system.metrics WHERE metric='TCPConnection'. Too low: "clickhouse: acquire conn timeout". Too high: server "Too many connections", FD limits exceeded. ClickHouse default max_connections: 1024 (shared).
ConnMaxLifetime time.Duration 1h conn_max_lifetime Both Max duration a connection can be reused. Checked on return to pool. 1-5h stable envs. 5-15m for K8s/rolling deploys. Never infinite. Too short (< 1m): churn, higher latency. Too long/infinite: stale connections, DNS changes not picked up, traffic never rebalances.
ConnMaxIdleTime time.Duration 0 (none) database/sql only Max time a connection can sit idle before closing. Not in Options struct – set via db.SetConnMaxIdleTime(). 5-10m for K8s/bursty workloads to reclaim idle connections after traffic spikes. Not set: idle connections persist until ConnMaxLifetime. Too short (< 30s): connections recreated during normal gaps.

See Connection Pooling for usage details.


Standard database/sql pool settings

When using clickhouse.OpenDB() or sql.Open("clickhouse", dsn), the returned *sql.DB supports Go’s standard pool methods. OpenDB() auto-applies the first three from Options:

Method Options equivalent Notes
db.SetMaxIdleConns(n) MaxIdleConns Auto-applied by OpenDB()
db.SetMaxOpenConns(n) MaxOpenConns Auto-applied by OpenDB()
db.SetConnMaxLifetime(d) ConnMaxLifetime Auto-applied by OpenDB()
db.SetConnMaxIdleTime(d) None Must be set manually post-creation

Compression

Option Type Default DSN param Description Best practice When misconfigured
Compression.Method CompressionMethod (byte) None compress (lz4, zstd, lz4hc, gzip, deflate, br, or true for LZ4) Compression algorithm for data transfer. See protocol support matrix below. LAN: None or LZ4. WAN: ZSTD or LZ4. CPU constrained: LZ4. Max compression: ZSTD (Native) or Brotli (HTTP). Skip for inserts < 1 MB. GZIP/Brotli on Native: handshake failure. LZ4HC on HTTP: error or silent fallback. No compression on slow networks: 10-100x slower inserts.
Compression.Level int 3 compress_level Algorithm-specific intensity. GZIP/Deflate: -2 to 9. Brotli: 0 to 11. LZ4/ZSTD: ignored. GZIP balanced: 3-6. Brotli balanced: 4-6. Very high levels: extreme CPU, minimal benefit. Non-zero for LZ4/ZSTD: silently ignored. Level without compression enabled: no effect.
MaxCompressionBuffer int (bytes) 10485760 (10 MiB) max_compression_buffer Max compression buffer size before flushing. Each connection has its own buffer. Default 10 MiB is good. 20-50 MiB for wide rows. Total memory = buffer x MaxOpenConns. Too small (< 1 MiB): frequent flushes, poor efficiency. Too large (> 100 MiB): OOM with many connections.

Compression method support by protocol:

Method Native HTTP
CompressionLZ4 Yes Yes
CompressionLZ4HC Yes No
CompressionZSTD Yes Yes
CompressionGZIP No Yes
CompressionDeflate No Yes
CompressionBrotli No Yes

TLS

Option Type Default DSN param Description Best practice When misconfigured
TLS *tls.Config nil (plain text) secure=true, skip_verify=true TLS/SSL config. Non-nil enables TLS. Ports: Native 9000/9440, HTTP 8123/8443. Always enable in production and ClickHouse Cloud (required). InsecureSkipVerify: false in production. Add custom CAs via RootCAs. Wrong port: "connection reset by peer". skip_verify=true in prod: MITM vulnerable. Expired cert: "x509: certificate has expired". Wrong host: "x509: certificate is valid for X, not Y". Untrusted CA: "x509: certificate signed by unknown authority". HTTP DSN with secure=true: use https:// scheme instead.

See TLS for code examples.


Logging

Option Type Default DSN param Description Best practice When misconfigured
Logger *slog.Logger nil (no logging) Structured logger via Go’s log/slog. Priority: Debug+Debugf > Logger > no-op. (Since v2.43.0) Use slog with JSON handler in production. Add app context with logger.With(...).
Debug (deprecated) bool false debug Legacy debug toggle. Use Logger instead. Logs to stdout unless Debugf is set. Enabled in production: performance overhead, verbose logs, sensitive data in output.
Debugf (deprecated) func(string, ...any) nil Custom debug log function. Use Logger instead. Requires Debug: true.
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
conn, err := clickhouse.Open(&clickhouse.Options{
    Logger: logger,
    // ...
})

See Logging for full examples.


Buffers and memory

Option Type Default DSN param Per-query Description Best practice When misconfigured
BlockBufferSize uint8 2 block_buffer_size Yes (WithBlockBufferSize) Decoded blocks to buffer when reading results. Enables concurrent read + decode. Default 2 is fine. 5-10 for large streaming results. Memory = buffer x block size x concurrent queries. Too small (1): blocks reader, higher latency. Too large (> 50): high memory, diminishing returns.
FreeBufOnConnRelease bool false No Release connection memory buffer after each query instead of reusing. false for high query rates. true in memory-constrained containers or infrequent large batches. false + limited memory: buffers accumulate (memory = buffer x idle conns). true + high rate: GC pressure, increased CPU.

HTTP-specific

Option Type Default DSN param Description Best practice When misconfigured
HttpHeaders map[string]string nil Additional HTTP headers on every request Use for tracing (X-Request-ID), auth proxy headers. Keep minimal. Overriding internal headers (Content-Type, Authorization): unpredictable behavior.
HttpUrlPath string "" http_path URL path appended to requests. Leading / added automatically. Use when behind reverse proxy with path routing. Wrong path: HTTP 404 from proxy/LB.
HttpMaxConnsPerHost int 0 (unlimited) TCP connections per host at transport layer (http.Transport.MaxConnsPerHost). Leave at 0 for most apps. Only set when server has strict connection limits. Too low (e.g., 10 with MaxOpenConns=50): transport bottleneck, slow queries despite low server load.
HTTPProxyURL *url.URL nil (uses env vars) http_proxy (URL-encoded) HTTP proxy for routing requests Set explicitly if proxy required. Overrides HTTP_PROXY/HTTPS_PROXY env vars. Wrong address: "dial tcp: lookup proxy: no such host". Proxy needs auth: HTTP 407.
TransportFunc func(*http.Transport) (http.RoundTripper, error) nil Custom HTTP transport factory. Receives default transport for wrapping. (Since v2.41.0) Use for observability middleware. Don’t override Proxy, DialContext, TLSClientConfig. Returning nil: panic. Overriding client fields: TLS/proxy silently ignored. Blocking RoundTripper: deadlocks.
TransportFunc: func(t *http.Transport) (http.RoundTripper, error) {
    return &loggingRoundTripper{transport: t}, nil
}

Advanced connection

Option Type Default DSN param Description Best practice When misconfigured
DialContext func(ctx, addr) (net.Conn, error) nil (standard dialer) Custom dial function for TCP connections. Works with both Native and HTTP. Leave nil for 99% of cases. Use for Unix sockets, SOCKS proxy, custom DNS. Not respecting context: hangs, resource leaks. With TLS set: custom dialer must handle TLS itself. Invalid net.Conn: crashes.
DialStrategy func(ctx, connID, options, dial) (DialResult, error) DefaultDialStrategy Custom server selection and connection strategy. Overrides ConnOpenStrategy. Use default for 99.9% of cases. Custom only for geo-aware routing, weighted selection, health checks. Not trying all servers: fails with healthy servers available. Expensive ops inside: blocks pool acquisition on every connect.

Client information

Option Type Default DSN param Per-query Description Best practice When misconfigured
ClientInfo ClientInfo struct Auto: clickhouse-go version + Go runtime client_info_product=myapp/1.0 Yes (WithClientInfo, appends) App identification sent to ClickHouse. Contains Products ([]struct{Name,Version}) and Comment ([]string). Visible in system.query_log. Always set app name + version. Query attribution: SELECT client_name FROM system.query_log WHERE client_name LIKE '%myapp%' Not setting: can’t identify which service issued queries in multi-service environments.
ClientInfo: clickhouse.ClientInfo{
    Products: []struct{ Name, Version string }{
        {Name: "my-service", Version: "1.0.0"},
    },
}
// Appears as: clickhouse-go/2.x my-service/1.0.0 (lv:go/1.23; os:linux)

ClickHouse server settings

Option Type Default DSN param Per-query Description Best practice When misconfigured
Settings map[string]any nil Any unrecognized param (e.g. ?max_execution_time=60) Yes (WithSettings, context wins on conflict) ClickHouse server settings applied to every query. DSN conversion: "true"1, "false"0, numeric→int. Set common limits at connection level, override per-query via context. Typos: silently ignored or error by version. Wrong types: "Cannot parse string 'abc' as Int64". max_execution_time=0 + no deadline: queries run forever.
CustomSetting CustomSetting{Value string} Yes (via WithSettings) Marks a setting as “custom” (non-important) for Native protocol. Won’t error if server doesn’t recognize it. HTTP treats all settings as custom by default. Use for experimental or version-specific settings. Marking important settings as custom: silently ignored if unsupported.

Common settings:

Setting Type Description
max_execution_time int Query timeout in seconds
max_memory_usage int Memory limit per query (bytes)
max_block_size int Block size for processing
readonly int 1 = read-only, 2 = read-only + settings changes
Settings: clickhouse.Settings{
    "max_execution_time":  60,                                        // important -- errors if unknown
    "my_custom_setting":   clickhouse.CustomSetting{Value: "value"},  // custom -- ignored if unknown
}

Context-level query options

Set per-query using clickhouse.Context():

ctx := clickhouse.Context(context.Background(),
    clickhouse.WithQueryID("my-query"),
    clickhouse.WithSettings(clickhouse.Settings{"max_execution_time": 60}),
)
Option Type Default Protocol Description Best practice When misconfigured
WithQueryID string Auto-generated Both Custom query identifier. Visible in system.query_log and system.processes. Use UUIDs. Useful for KILL QUERY WHERE query_id='...'. Duplicate IDs: confusion in system.query_log.
WithQuotaKey string "" Both Quota key for multi-tenant resource limits. Requires server-side quota config. Use for per-customer/per-user limits. Quota not configured: silently ignored.
WithJWT string "" HTTPS only Per-query JWT override for ClickHouse Cloud. (Since v2.35.0) Use for per-request auth in multi-tenant proxies. Without TLS: ignored, falls back to connection auth. Expired: "Token has expired".
WithSettings Settings Inherits connection Both Per-query server settings. Merged with connection settings; context wins on conflict. Override max_execution_time or max_rows_to_read per query type. Same as connection-level Settings.
WithParameters Parameters (map[string]string) nil Both Server-side parameterized query values. Query syntax: {param_name:Type}. Use instead of string concatenation for SQL injection safety. Missing param: "Substitution {param_name:Type} isn't set". Wrong type: "Cannot parse string 'abc' as UInt64".
WithAsync bool (wait) Sync Both Async insert mode. Sets async_insert=1. wait=true adds wait_for_async_insert=1. Requires ClickHouse 21.11+. (Since v2.41.0; supersedes the older WithStdAsync.) Use for high-throughput inserts. wait=false: errors may be async – check system.asynchronous_insert_log. With SELECT: ignored. Old server: "Unknown setting async_insert".
WithLogs func(*Log) nil Native only Server log entries callback during query execution. Keep fast – blocks execution. Use goroutines for heavy processing. On HTTP: silently never called.
WithProgress func(*Progress) nil Native only Query progress updates (rows/bytes processed). Keep fast – blocks execution. On HTTP: silently never called.
WithProfileInfo func(*ProfileInfo) nil Native only Query execution statistics callback. Keep fast – blocks execution. On HTTP: silently never called.
WithProfileEvents func([]ProfileEvent) nil Native only Performance counters callback. Keep fast – blocks execution. On HTTP: silently never called.
WithoutProfileEvents Events sent Native only Suppress profile events. Performance optimization for servers ≥ 25.11. (Since v2.44.0) Use when you don’t need profile events. On older servers: error for unknown setting.
WithExternalTable ...*ext.Table nil Both Attach temporary lookup tables to query. Data transferred per query. Keep tables < 10 MB. Native more efficient than HTTP (multipart). Large tables: network overhead per query.
WithUserLocation *time.Location Server timezone Both Override timezone for DateTime parsing. Set explicitly when client/server timezones differ. Wrong timezone: DateTime values silently off by hours, potential data corruption.
WithColumnNamesAndTypes []ColumnNameAndType nil (runs DESCRIBE) HTTP only Skip DESCRIBE TABLE round trip on HTTP inserts by providing column info upfront. (Since v2.37.0) Use when schema is known and stable. Wrong types: "Cannot convert String to UInt64". Schema drift after migration: stale info.
WithBlockBufferSize uint8 Connection-level (2) Both Override connection-level BlockBufferSize for a single query. Increase for large result sets on specific queries.
WithClientInfo ClientInfo Connection-level Both Append additional client info for a single query. Does not replace, appends. (Since v2.42.0) Add per-request context (e.g., endpoint name).
WithSpan trace.SpanContext Empty Native only OpenTelemetry span context for distributed tracing. See OpenTelemetry.
ctx := clickhouse.Context(ctx,
    clickhouse.WithQueryID("query-123"),
    clickhouse.WithParameters(clickhouse.Parameters{
        "user_id": "12345",
    }),
    clickhouse.WithProgress(func(p *clickhouse.Progress) {
        log.Printf("Progress: %d rows, %d bytes", p.Rows, p.Bytes)
    }),
)
rows, err := conn.Query(ctx, "SELECT * FROM users WHERE id = {user_id:String}")

Batch options

Passed to PrepareBatch(). Import: github.com/ClickHouse/clickhouse-go/v2/lib/driver.

Option Default Description Best practice When misconfigured
WithReleaseConnection Connection held until Send() Release connection to pool immediately after PrepareBatch(). Re-acquires on Send()/Flush(). Use for long-lived batches (minutes/hours) to prevent pool exhaustion. Not using for long batches: "acquire conn timeout" if many active.
WithCloseOnFlush Batch stays open Auto-close batch when Flush() is called. Use for one-shot batches. Saves explicit Close(). Using with multiple Flush() calls: first flush closes batch, subsequent ops fail.
batch, err := conn.PrepareBatch(ctx, "INSERT INTO table",
    driver.WithReleaseConnection(),
    driver.WithCloseOnFlush(),
)

Quick reference tables

Connection pool sizing recommendations

Application type MaxIdleConns MaxOpenConns ConnMaxLifetime
Low-traffic web app 5 10 1h
Medium-traffic API 20 50 30m
High-traffic service 50 100 15m
Background batch jobs 10 20 2h
Kubernetes deployment 10 20 10m
Serverless (Lambda) 1 5 5m

Timeout recommendations

Environment DialTimeout ReadTimeout
Local / LAN 5s 30s
Cloud, same region 10s 2m
Cloud, cross region 30s 5m
OLAP workload 10s 30m
Realtime / OLTP 5s 10s

DSN parameter quick reference

DSN parameter Options field Example
username Auth.Username ?username=admin
password Auth.Password ?password=secret
database Auth.Database ?database=mydb or /mydb in path
dial_timeout DialTimeout ?dial_timeout=10s
read_timeout ReadTimeout ?read_timeout=5m
max_open_conns MaxOpenConns ?max_open_conns=50
max_idle_conns MaxIdleConns ?max_idle_conns=20
conn_max_lifetime ConnMaxLifetime ?conn_max_lifetime=30m
connection_open_strategy ConnOpenStrategy ?connection_open_strategy=round_robin
block_buffer_size BlockBufferSize ?block_buffer_size=10
compress Compression.Method ?compress=lz4
compress_level Compression.Level ?compress_level=6
max_compression_buffer MaxCompressionBuffer ?max_compression_buffer=20971520
secure TLS ?secure=true
skip_verify TLS.InsecureSkipVerify ?skip_verify=true
debug Debug ?debug=true
client_info_product ClientInfo.Products ?client_info_product=myapp/1.0
http_proxy HTTPProxyURL ?http_proxy=http%3A%2F%2Fproxy%3A8080
http_path HttpUrlPath ?http_path=/clickhouse
(any other) Settings[key] ?max_execution_time=60

Troubleshooting

Connection pool exhausted: “acquire conn timeout”

Cause: Connection pool exhausted - all MaxOpenConns connections are in use and none became available within DialTimeout.

Fix

Try the following steps in order, and diagnose the root cause before tuning knobs:

  1. Check for long-running queries holding connections: SELECT query_id, elapsed FROM system.processes ORDER BY elapsed DESC. If found, address the slow queries first.
  2. If you run long-lived batches (minutes/hours between PrepareBatch() and Send()), use WithReleaseConnection() to return the connection to the pool while the batch is open.
  3. Increase MaxOpenConns to match observed concurrency.
  4. Increase DialTimeout only if bursts are expected and acquisition wait is the actual bottleneck.

Read timeout and connection reset errors

Cause: ReadTimeout exceeded while waiting for a server response, or the connection was closed by the server/network.

Fix:

  • Increase ReadTimeout for long-running queries
  • Use context deadlines for per-query timeout control
  • Check ClickHouse server-side max_execution_time limits

“Code: 516. Authentication failed”

Cause: Wrong username, password, or the user doesn’t exist.

Fix:

  • Verify credentials against system.users table
  • Check for URL-encoding issues with special characters in DSN passwords
  • Confirm the user has access to the specified database

TLS certificate errors

Error Cause Fix
x509: certificate has expired Server cert expired Renew server certificate
x509: certificate is valid for X, not Y Hostname mismatch Use correct hostname or add to SANs
x509: certificate signed by unknown authority Untrusted CA Add CA to tls.Config.RootCAs
connection reset by peer TLS/port mismatch Use port 9440 (Native) or 8443 (HTTP) for TLS

Gradual memory growth

Cause: Large idle connection buffers accumulating.

Fix:

  • Set FreeBufOnConnRelease: true in memory-constrained environments
  • Reduce MaxIdleConns to limit idle connections
  • Reduce MaxCompressionBuffer if using compression
  • Lower ConnMaxLifetime to cycle connections more frequently
Navigation