Skip to main content
Java client library to communicate with a DB server through its protocols. The current implementation only supports the HTTP interface. The library provides its own API to send requests to a server. The library also provides tools to work with different binary data formats (RowBinary* & Native*).

Setup



Initialization

The Client object is initialized by com.clickhouse.client.api.Client.Builder#build(). Each client has its own context and no objects are shared between them. The Builder has configuration methods for convenient setup.Example:
showLineNumbers
Client is AutoCloseable and should be closed when not needed anymore.

Authentication

Authentication is configured per client at the initialization phase. There are three authentication methods supported: by password, by access token, by SSL Client Certificate.Authentication by a password requires setting user name password by calling setUsername(String) and setPassword(String):
showLineNumbers
Authentication by an access token or Bearer token (such as a JWT) requires setting the token by calling useBearerTokenAuth(String) (or setAccessToken(String) for raw access tokens):
showLineNumbers
Authentication by a SSL Client Certificate require setting username, enabling SSL Authentication, setting a client certificate and a client key by calling setUsername(String), useSSLAuthentication(boolean), setClientCertificate(String) and setClientKey(String) accordingly:
showLineNumbers
SSL Authentication may be hard to troubleshoot on production because many errors from SSL libraries provide not enough information. For example, if client certificate and key don’t match then server will terminate connection immediately (in case of HTTP it will be connection initiation stage where no HTTP requests are send so no response is sent).Please use tools like openssl to verify certificates and keys:
  • check key integrity: openssl rsa -in [key-file.key] -check -noout
  • check client certificate has matching CN for a user:
    • get CN from an user certificate - openssl x509 -noout -subject -in [user.cert]
    • verify same value is set in database select name, auth_type, auth_params from system.users where auth_type = 'ssl_certificate' (query will output auth_params with something like {"common_names":["some_user"]})

Connection Pooling

The Client uses Apache HttpClient 5 with an internal HTTP connection pool. Each operation borrows a connection from the pool, sends the request, streams the response, and returns the connection to the pool.Key connection pool settings on Client.Builder:
showLineNumbers

Configuration

All settings are defined by instance methods (a.k.a configuration methods) that make the scope and context of each value clear. Major configuration parameters are defined in one scope (client or operation) and don’t override each other.Configuration is defined during client creation. See com.clickhouse.client.api.Client.Builder.

Client Configuration


Client Identification

There are two fields in a query log that identify application originated a request: client_name and http_user_agent. Native TCP protocol uses client_name to identify application. HTTP protocol uses http_user_agent to identify application. Client builder has method setClientName correct values for both protocols. The field http_user_agent is set according to User-Agent header common format: application-name[/version] [(operating-system; architecture; ...)]. This set of values is repeated for each layer: application, client library, http client library. What is set by setClientName method comes first in the list.For example:
showLineNumbers
will result in the following http_user_agent value:
Application can set own http header User-Agent to identify itself. But part clickhouse-java-v2/0.9.6-SNAPSHOT will be appended to the end of the header.

Operation Identification

Query log has another two fields query_id and log_comment that can be used to identify an operation and add additional information to the query log.query_id is a unique identifier of an operation. It can be set by application by calling setQueryId method of the QuerySettings class.
showLineNumbers
log_comment is a comment that can be added to the query log. It can be set by application by calling logComment method of the QuerySettings class.
showLineNumbers

Server Settings

Server side settings can be set on the client level once while creation (see serverSetting method of the Builder) and on operation level (see serverSetting for operation settings class).
showLineNumbers
⚠️ When options are set via setOption method (either the Client.Builder or operation settings class) then server settings name should be prefixed with clickhouse_setting_. The com.clickhouse.client.api.ClientConfigProperties#serverSetting() may be handy in this case.

Custom HTTP Headers

Custom HTTP headers can be set for all operations (client level) or a single one (operation level). Operation settings override client-level headers with the same name.
showLineNumbers
Important: When options are set via setOption (on Client.Builder or an operation settings class), prefix the header name with http_header_. ClientConfigProperties.httpHeader(String) builds that key. As header name is simple String key it should be in one letter case otherwise duplicate values will result undefined behavior, ClientConfigProperties.httpHeader(String) fixes this problem.
showLineNumbers

ClickHouse Cloud Features

Features that apply when connecting to ClickHouse Cloud.

Replica-aware Routing (CLOUD)

ClickHouse Cloud can pin related HTTP requests to the same replica. Send the X-ClickHouse-Replica-Tag header so a Cloud proxy routes every request that shares the tag to one replica. Use this for session-scoped objects such as temporary tables, replica-local cache reuse, or read-after-write consistency. Read more: https://clickhouse.com/docs/products/cloud/features/infrastructure/replica-aware-routing.What to set: HTTP header X-ClickHouse-Replica-Tag (com.clickhouse.client.api.http.ClickHouseHttpProto.HEADER_REPLICA_TAG). Use the same tag value for all requests that should stay on one replica.
showLineNumbers
To configure per operation, set the header on QuerySettings, InsertSettings, or CommandSettings instead of the client builder.

JWT Authentication (CLOUD)

JWT Authentication allows authenticating users with JSON Web Tokens (JWTs) in ClickHouse Cloud. Instead of pre-existing database users, ClickHouse dynamically creates ephemeral users derived from claims embedded in each token.

Initial Configuration

To configure initial JWT authentication on the client, use useBearerTokenAuth(token) (this automatically adds Bearer_ prefix. (see HTTP interface docs ) when building the Client instance:
showLineNumbers
useBearerTokenAuth(token) automatically prepends the Bearer prefix to the Authorization HTTP header.

Updating Token at Runtime

Because JWTs are short-lived and ephemeral users exist only for the token’s lifetime, new JWT tokens should be set before the current token expires so no operations fail.You can update the bearer token on an existing Client instance at runtime without recreating the client:
showLineNumbers
All subsequent requests on the Client instance will use the updated JWT token.

Common Definitions

ClickHouseFormat

Enum of supported formats. It includes all formats that ClickHouse supports.
  • raw - user should transcode raw data
  • full - the client can transcode data by itself and accepts a raw data stream
  • - - operation not supported by ClickHouse for this format
This client version supports:

Insert API

insert(String tableName, InputStream data, ClickHouseFormat format)

Accepts data as an InputStream of bytes in the specified format. It is expected that data is encoded in the format.Signatures
ParameterstableName - a target table name.data - an input stream of an encoded data.format - a format in which the data is encoded.settings - request settings.Return valueFuture of InsertResponse type - result of the operation and additional information like server side metrics.Examples
showLineNumbers

insert(String tableName, List<?> data, InsertSettings settings)

Sends a write request to database. The list of objects is converted into an efficient format and then is sent to a server. The class of the list items should be registered up-front using register(Class, TableSchema) method.Signatures
ParameterstableName - name of the target table.data - collection DTO (Data Transfer Object) objects.settings - request settings.Return valueFuture of InsertResponse type - the result of the operation and additional information like server side metrics.Examples
showLineNumbers

InsertSettings

Configuration options for insert operations.Configuration methods

InsertResponse

Response object that holds result of insert operation. It is only available if the client got response from a server.
This object should be closed as soon as possible to release a connection because the connection can’t be re-used until all data of previous response is fully read.

Query API

Format SelectionClient provides transparent access to the response stream from server. User is free to choose any ClickHouse format in request and read data via InputStream from QueryResponse object. Format can be requested via:
  • QuerySettings#setFormat() this will set format header in a request.
  • In FORMAT clause in query itself.
  • Server settings default_format (/reference/settings/session-settings/default#default_format)
There are differences in behavior depending on ClickHouse and Client version:
  • Client < 0.11.0 & ClickHouse < 26.8 - FORMAT clause has priority over request format header.
  • Client > 0.11.0 & ClickHouse > 26.8 - request header has priority over FORMAT clause.
    • Client sets header when no format is specified in QuerySettings - this doesn’t allow to override format in query.
  • Client starting 0.11.0 - sets default format value on client level and not on operation level. This allows existing code work without changes and new code to use FORMAT clause by settings format on client to null.

query(String sqlQuery)

Sends sqlQuery as is. Response format is set by query settings. QueryResponse will hold a reference to the response stream that should be consumed by a reader for the supportig format.Signatures
ParameterssqlQuery - a single SQL statement. The Query is sent as is to a server.settings - request settings.Return valueFuture of QueryResponse type - a result dataset and additional information like server side metrics. The Response object should be closed after consuming the dataset.Examples

query(String sqlQuery, Map<String, Object> queryParams, QuerySettings settings)

Sends sqlQuery as is. Additionally will send query parameters so the server can compile the SQL expression.Signatures
ParameterssqlQuery - sql expression with placeholders {}.queryParams - map of variables to complete the sql expression on server.settings - request settings.Return valueFuture of QueryResponse type - a result dataset and additional information like server side metrics. The Response object should be closed after consuming the dataset.Examples
showLineNumbers

queryAll(String sqlQuery)

Queries a data in RowBinaryWithNamesAndTypes format. Returns the result as a collection. Read performance is the same as with the reader but more memory is required to hold the whole dataset.Signatures
ParameterssqlQuery - sql expression to query data from a server.Return valueComplete dataset represented by a list of GenericRecord objects that provide access in row style for the result data.Examples
showLineNumbers

QuerySettings

Configuration options for query operations.Configuration methods

QueryResponse

Response object that holds result of query execution. It is only available if the client got a response from a server.
This object should be closed as soon as possible to release a connection because the connection can’t be re-used until all data of previous response is fully read.

Examples

Common API

getTableSchema(String table)

Fetches table schema for the table.Signatures
Parameterstable - table name for which schema data should be fetched.database - database where the target table is defined.Return valueReturns a TableSchema object with list of table columns.

getTableSchemaFromQuery(String sql)

Fetches schema from a SQL statement.Signatures
Parameterssql - “SELECT” SQL statement which schema should be returned.Return valueReturns a TableSchema object with columns matching the sql expression.

TableSchema

register(Class<?> clazz, TableSchema schema)

Compiles serialization and deserialization layer for the Java Class to use for writing/reading data with schema. The method will create a serializer and deserializer for the pair getter/setter and corresponding column. Column match is found by extracting its name from a method name. For example, getFirstName will be for the column first_name or firstname.Signatures
Parametersclazz - Class representing the POJO used to read/write data.schema - Data schema to use for matching with POJO properties.Examples
showLineNumbers

Usage Examples

Complete examples code is stored in the repo in a ‘example` folder:

Reading Data

There are two common ways to read data:
  • query() method that returns low-level QueryResponse object that contains InputStream with data. Usually combined with ClickHouseBinaryFormatReader for streaming reads but can be used with any other custom reader implementation. QueryResponse also provides access to the result set metadata and metrics.
  • queryAll() method and using GenericRecord for convenient row access. In this case the whole result set is loaded into memory.
  • queryRecords() method that returns com.clickhouse.client.api.query.Records - an iterator for GenericRecord objects. This method uses streaming approach (no data is loaded into memory) and utilises GenericRecord to access data.
Note: streaming approach requires fast read otherwise it may cause server write timeout because data is read directly from the network stream.

Reading Arrays

ClickHouseBinaryFormatReader Methods
  • getList(...) - reads any Array(...) as List<T>. Good default for flexible typed reads. Supports nested arrays.
  • getByteArray(...), getShortArray(...), getIntArray(...), getLongArray(...), getFloatArray(...), getDoubleArray(...), getBooleanArray(...) - best for 1D arrays of primitive-compatible values.
  • getStringArray(...) - for Array(String) (and enum values represented as names).
  • getObjectArray(...) - generic option for any Array(...) element type, including nested arrays. Use to read arrays with nullable values and nested arrays.
Index-based and name-based overloads are available for all methods. Index is 1-based. Index-based do direct access to a column. Name-based methods require index lookup each time.
GenericRecord Methods
  • getList(...) - reads any Array(...) as List<T>. Good default for flexible typed reads. Supports nested arrays.
  • getByteArray(...), getShortArray(...), getIntArray(...), getLongArray(...), getFloatArray(...), getDoubleArray(...), getBooleanArray(...) - best for 1D arrays of primitive-compatible values.
  • getStringArray(...) - for Array(String) (and enum values represented as names).
  • getObjectArray(...) - generic option for any Array(...) element type, including nested arrays. Use to read arrays with nullable values and nested arrays.
Index-based and name-based overloads are available for all methods. Index is 1-based. Index-based do direct access to a column. Name-based methods require index lookup each time.

Observability & Monitoring

The ClickHouse Java Client (V2) provides built-in observability features designed around OpenTelemetry semantic conventions and Micrometer metrics. The client enables monitoring operational durations, throughput, retries, server execution statistics, connection pool status, and distributed tracing spans.For a complete production-style Spring Boot application demonstrating Client V2 configuration, connection pooling, trace context propagation across @Async boundaries, and full telemetry integration, see the examples/demo-spring-service module in this repository.

Client Builder Observability API

The Client.Builder exposes three primary methods to configure observability and metrics collection:
  • setMetricsRecorder(MetricsRecorder recorder): Registers a metrics recorder for exporting operational metrics (durations, counts, retries, errors). When not explicitly set, defaults to DefaultMetricsRecorder.NOOP.
  • setSpanRecorder(SpanRecorder recorder): Registers a span recorder for distributed tracing (operation spans and transport request spans). When not explicitly set, defaults to DefaultSpanRecorder.NOOP.
  • registerClientMetrics(Object registry, String groupName): Binds Apache HttpClient connection pool metrics (such as available and leased connections, pending requests, and connection creation time) to a Micrometer MeterRegistry.
Dependencies RequirementThe built-in OpenTelemetrySpanRecorder and MicrometerMetricsRecorder classes are provided as part of the client-v2 package. However, they require the OpenTelemetry API (io.opentelemetry:opentelemetry-api) and Micrometer (io.micrometer:micrometer-core) libraries to be present on the application’s classpath at runtime. The main client artifact does not bundle these third-party dependencies nor pull them in transitively. Applications using OpenTelemetry tracing or Micrometer metrics must explicitly declare these dependencies in their project build configuration (pom.xml or build.gradle).Builder Configuration Example
Integration ApproachesApplications can integrate observability using two primary patterns:
  1. OpenTelemetry Agent & Global Autoconfiguration:
    • For applications using the OpenTelemetry Java Agent or global SDK autoconfiguration, instantiate OpenTelemetrySpanRecorder and MicrometerMetricsRecorder using their default no-argument constructors.
    • The default constructors automatically bind to GlobalOpenTelemetry.get() and Micrometer’s Metrics.globalRegistry.
  2. Explicit Client-Level Integration:
    • Pass explicitly created OpenTelemetry, Tracer, or Micrometer MeterRegistry instances directly into the recorder constructors.
    • Ideal when managing multiple isolated clients or multi-tenant services with independent telemetry sinks.

Metrics Reported

Operational Metrics

Metrics exported via MetricsRecorder follow the OpenTelemetry semantic conventions for database client metrics (MetricName and MetricAttribute):

Metric Attributes / Tags

Meters created by MicrometerMetricsRecorder carry low-cardinality tags (MetricAttribute):

Connection Pool Metrics

When calling registerClientMetrics(meterRegistry, "groupName"), HTTP connection pool gauges are registered with Micrometer:
  • httpcomponents.httpclient.pool.total.max: Configured maximum allowed persistent connections.
  • httpcomponents.httpclient.pool.total.connections (tagged with state="available" or state="leased"): Active connections in the pool.
  • httpcomponents.httpclient.pool.total.pending: Number of connection requests awaiting a free connection.
  • httpcomponents.httpclient.pool.route.max.default: Configured default maximum connections per route.
  • httpcomponents.httpclient.connect.time: Running average connection establishment time.

Response Metrics API

In addition to metrics recorders, detailed execution statistics are accessible directly on response objects (QueryResponse, InsertResponse) via OperationMetrics:

Spans Reported

Tracing in Client V2 produces two types of spans arranged in a parent-child hierarchy:
  1. Operation Span: Represents a high-level client operation (QUERY <database> or INSERT <database>.<table_name>). Started under the current thread’s trace context (Context.current()) so that database operations join the caller’s active trace span.
  2. Transport Request Span: Represents an individual HTTP transport request attempt (POST). Created as a child of the corresponding operation span. Each retry attempt creates a new transport request span under the operation span.

Span Attributes

Spans are populated with standard OpenTelemetry attributes (SpanAttribute):
Context Propagation Across Asynchronous Boundaries: Because Client V2 inherits Context.current(), operations started on threads with an active trace span automatically join the trace. When delegating tasks across thread pools (e.g., Spring @Async or custom ExecutorService), propagate the OpenTelemetry context explicitly:

Developing Custom Recorders

Applications with custom observability backends can implement custom recorders by extending DefaultMetricsRecorder (for metrics) or DefaultSpanRecorder (for tracing).
  • DefaultMetricsRecorder: Base implementation of MetricsRecorder. Override specific callbacks like recordQuerySuccess or recordQueryFailure. Use MetricsSupport.DEFAULT to derive standard metric names (MetricName), units, and attribute maps (MetricAttribute).
  • DefaultSpanRecorder: Base implementation of SpanRecorder. Override span creation callbacks like startQuerySpan, startInsertSpan, or startRequestSpan. Use SpanSupport.DEFAULT to calculate standard OpenTelemetry span names and attributes (SpanAttribute).
For production reference implementations, see the built-in client classes:
  • com.clickhouse.client.api.observability.otel.OpenTelemetrySpanRecorder (OpenTelemetry tracing integration)
  • com.clickhouse.client.api.observability.micrometer.MicrometerMetricsRecorder (Micrometer metrics integration)

Migration Guide

Old client (V1) was using com.clickhouse.client.ClickHouseClient#builder as start point. The new client (V2) uses similar pattern with com.clickhouse.client.api.Client.Builder. Main differences are:
  • no service loader is used to grab implementation. The com.clickhouse.client.api.Client is facade class for all kinds of implementation in the future.
  • a fewer sources of configuration: one is provided to the builder and one is with operation settings (QuerySettings, InsertSettings). Previous version had configuration per node and was loading env. variables in some cases.

Configuration Parameters Match

There are 3 enum classes related to configuration in V1:
  • com.clickhouse.client.config.ClickHouseDefaults - configuration parameters that supposed to be set in most use cases. Like USER and PASSWORD.
  • com.clickhouse.client.config.ClickHouseClientOption - configuration parameters specific for the client. Like HEALTH_CHECK_INTERVAL.
  • com.clickhouse.client.http.config.ClickHouseHttpOption - configuration parameters specific for HTTP interface. Like RECEIVE_QUERY_PROGRESS.
They were designed to group parameters and provide clear separation. However in some cases it lead to a confusion (is there a difference between com.clickhouse.client.config.ClickHouseDefaults#ASYNC and com.clickhouse.client.config.ClickHouseClientOption#ASYNC). The new V2 client uses com.clickhouse.client.api.Client.Builder as single dictionary of all possible client configuration options.There is com.clickhouse.client.api.ClientConfigProperties where all configuration parameter names are listed.Table below shows what old options are supported in the new client and their new meaning.Legend: ✔ = supported, ✗ = dropped

General Differences

  • Client V2 uses less proprietary classes to increase portability. For example, V2 works with any implementation of java.io.InputStream for writing data to a server.
  • Client V2 async settings is off by default. It means no extra threads and more application control over client. This setting should be off for majority of use cases. Enabling async will create a separate thread for a request. It only make sense when using application controlled executor (see com.clickhouse.client.api.Client.Builder#setSharedOperationExecutor)

Writing Data

  • use any implementation of java.io.InputStream. V1 com.clickhouse.data.ClickHouseInputStream is supported but NOT recommended.
  • once end of input stream is detected it handled accordingly. Previously output stream of a request should be closed.
V1 Insert TSV formatted data.
V2 Insert TSV formatted data.
  • there is a single method to call. No need to create an additional request object.
  • request body stream is closed automatically when all data is copied.
  • new low-level API is available com.clickhouse.client.api.Client#insert(java.lang.String, java.util.List<java.lang.String>, com.clickhouse.client.api.DataStreamWriter, com.clickhouse.data.ClickHouseFormat, com.clickhouse.client.api.insert.InsertSettings). com.clickhouse.client.api.DataStreamWriter is designed to implement custom data writing logic. For instance, reading data from a queue.

Reading Data

  • Data is read in RowBinaryWithNamesAndTypes format by default. Currently only this format is supported when data binding is required.
  • Data can be read as a collection of records using List<GenericRecord> com.clickhouse.client.api.Client#queryAll(java.lang.String) method. It will read data to a memory and release connection. No need for extra handling. GenericRecord gives access to data, implements some conversions.