clickhouse-go v2: the Go driver for ClickHouse, and when to use the native interface
Golang driver for ClickHouse
At a glance
- What is it?
- clickhouse-go is the official Go client for ClickHouse, offering a ClickHouse-specific API and a database/sql wrapper. The native interface is faster; the standard one fits existing ORMs. The choice is the whole story.
- Who is it for?
- Adopt clickhouse-go if you write new Go code against ClickHouse and want direct column encoding, batch inserts and context-carried settings. Stay with database/sql only if an existing ORM or tool already depends on it, and accept the slower path.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap clickhouse-go fills between Go and ClickHouse
ClickHouse speaks its own columnar protocol. A generic SQL driver cannot exploit that: it hands rows to database/sql as a sequence of values, and the columnar shape is lost on the way in and out. clickhouse-go exists to keep that shape. It is the official Golang SQL database client for ClickHouse, published under Apache-2.0, and it is aimed at Go engineers who query or write to ClickHouse from application code, ETL jobs or services.
The driver's own comparison table frames the intended audience. New code and performance-sensitive work belong on clickhouse.Open, the native interface, which exposes driver.Conn with ClickHouse-specific methods. Existing database/sql tooling and ORMs belong on sql.Open or clickhouse.OpenDB. The README states plainly that the standard interface is slower than the native one and links to a benchmark to back the claim. Both interfaces support TCP and HTTP transport, so the transport decision is separate from the API decision.
If you are already holding a *sql.DB from another database and want to swap the backend, the standard interface is the honest fit. If you are starting fresh, the README's advice is to use the native interface when in doubt.
How the native and database/sql paths differ under the hood
From version 2.3.0 onward the driver delegates encoding, decoding and compression to ch-go, a lower-level ClickHouse client. That is the mechanism behind the performance claim: values are encoded directly into ClickHouse's native column format rather than being translated through database/sql's row abstraction. The driver also supports LZ4, ZSTD, LZ4HC, GZIP, Deflate and Brotli compression, and the README recommends LZ4 in its sample options.
The repository layout reflects two transport implementations living side by side. conn.go and conn_handshake.go sit alongside conn_http.go, conn_http_query.go, conn_http_exec.go and conn_http_batch.go. Connection pooling has its own file, conn_pool.go, and async inserts get conn_async_insert.go plus an HTTP counterpart. So the same logical operation, a batch write, has a native TCP path and a separate HTTP path, each with its own file.
Context is the other architectural thread. The README lists Query ID, Quota Key, Settings, server-side query parameters, OpenTelemetry and execution events (logs, progress, profile info, profile events) as features carried through Context. That means per-query settings travel with the call rather than being baked into the connection. The trade-off is that any code path which drops the context silently loses those knobs.
Installing clickhouse-go and running a first query
The README gives one install command. It pulls the v2 module path, which is what current releases use (v2.48.0 was published on 2026-08-04).
go get github.com/ClickHouse/clickhouse-go/v2After that, the shortest real use is the native interface. The README's own example opens a connection to 127.0.0.1:9000, the native TCP port, with the default database and user. The DialContext hook is optional but useful: it lets you count or wrap dials, and the example increments a counter there.
conn, err := clickhouse.Open(&clickhouse.Options{
Addr: []string{"127.0.0.1:9000"},
Auth: clickhouse.Auth{
Database: "default",
Username: "default",
Password: "",
},
Settings: clickhouse.Settings{
"max_execution_time": 60,
},
Compression: &clickhouse.Compression{
Method: clickhouse.CompressionLZ4,
},
})
if err != nil {
return err
}
return conn.Ping(context.Background())If you need a server to point it at, the repository ships a docker-compose.yml with the clickhouse/clickhouse-server image. It publishes 8123 (HTTP), 9000 (native TCP) and 9009, all bound to 127.0.0.1, and defines a healthcheck against http://127.0.0.1:8123/ping. The Makefile wraps this: make up runs docker compose up --wait, and make down tears it down.
make upFor the standard interface, the shape changes. clickhouse.OpenDB returns something you then configure with SetMaxIdleConns, SetMaxOpenConns and SetConnMaxLifetime, exactly like any other database/sql handle. The README's OpenDB example points at port 9999 and sets InsecureSkipVerify in its TLS config, which is a sample value rather than a recommendation. There is also a DSN form with keys such as hosts, alt_hosts, username, password, database, dial_timeout, connection_open_strategy, debug and compress. The compress key accepts none, zstd, lz4, lz4hc, gzip, deflate or br, and setting it to true selects lz4.
Where clickhouse-go is the wrong tool
The standard interface is explicitly the slower one, and the README says so twice. If your workload is a high-volume insert path and you chose sql.Open for familiarity, you have paid a cost the documentation warned about. That is a design decision you can reverse, but it means the driver's own comparison table is the first thing to read, not the last.
The arbitrary input and output formats feature, which lets you stream results or inserts as raw CSV, JSONEachRow or Parquet, is marked experimental and is HTTP-only. If your deployment uses native TCP, that capability is not available to you regardless of how useful it would be.
Go version support is another hard boundary. The README's compatibility table maps client versions to Go versions: client >= 2.41 targets Go 1.24 and 1.25, while client >= 2.29 covers 1.21 through 1.24. The repository's go.mod declares go 1.25.0 with toolchain go1.25.4. A team pinned to an older Go release has to pick a client version deliberately rather than taking the latest.
Finally, the driver is tested against the currently supported ClickHouse versions, not every version ever released. If you run an old server, that combination is outside what the README claims.
clickhouse-go against ClickHouse-connect and ClickHouse-rs
The obvious alternative for a Go shop is not another Go driver but a different language client. ClickHouse-connect is the Python client, and ClickHouse-rs is the Rust one. They solve the same problem, reaching ClickHouse from an application, but they change the deployment shape rather than the API.
Choosing ClickHouse-connect means your data path runs through a Python service. You gain Python's ecosystem for data manipulation and lose the compile-time type checking that makes clickhouse-go's struct marshalling useful: ScanStruct and Select map columns into Go structs, and AppendStruct goes the other direction. ClickHouse-rs gives you Rust's ownership model and a comparable performance profile, at the cost of a Rust build in your pipeline.
The real question is where the code lives. If the service writing to ClickHouse is already Go, introducing a Python sidecar to talk to the database adds a network hop and a second runtime. If it is already Python, clickhouse-go is not a candidate at all. Between the Go driver's two interfaces the choice is narrower: native for new code, database/sql for existing ORM investment.
Release cadence, licensing and what upgrades cost
The last push to the repository was on 2026-09-16, and recent releases landed on 2026-08-04 (v2.48.0), 2026-06-26 (v2.47.0) and 2026-05-03 (v2.46.0). That is a steady cadence of roughly every one to two months. The repository is not archived.
Upgrade cost is mostly a Go version question. Because the compatibility table ties client versions to Go versions, bumping the driver can force a toolchain bump. The go.mod currently requires go 1.25.0, so a project on Go 1.23 cannot simply take the newest tag.
The dependency tree is worth a look before adopting. The direct requires include ch-go v0.74.0, brotli, shopspring/decimal, paulmach/orb, google/uuid and go.opentelemetry.io/otel/trace, with a large indirect set that includes testcontainers, Docker client packages and klauspost/compress. Some of that weight is test infrastructure rather than runtime code, but a dependency audit will see it.
The licence is Apache-2.0, the same permissive family most Go infrastructure uses. That permits commercial use and modification with attribution and patent terms attached. This is a description of the licence identifier, not legal advice; if your organisation has a policy on Apache-2.0 dependencies, run it through that process.
Editorial conclusion
Adopt clickhouse-go if you write new Go code against ClickHouse and want direct column encoding, batch inserts and context-carried settings. Stay with database/sql only if an existing ORM or tool already depends on it, and accept the slower path. Before committing, verify the Go version your toolchain runs against the compatibility table and confirm which interface your code actually opens, because the two are separate entry points in the same module.
Frequently asked questions
What is ClickHouse used for?
ClickHouse is the analytics database this driver connects to. The repository describes clickhouse-go as a Golang SQL database client for ClickHouse, and the driver's features such as batch writes, async inserts and column-oriented encoding are aimed at analytical workloads.
Can I use ClickHouse for free?
The driver is published under Apache-2.0, and the repository's docker-compose.yml pulls the clickhouse/clickhouse-server image, which is how the project's own test setup runs a server. ClickHouse's own licensing and pricing are not covered by the driver's documentation.
How do I install clickhouse-go?
The README gives a single command, go get github.com/ClickHouse/clickhouse-go/v2. The module path carries the v2 major version, which is what current releases use.
Should I use clickhouse.Open or sql.Open with clickhouse-go?
The README's comparison table recommends the native interface (clickhouse.Open) for new code and performance-sensitive work, and the database/sql path for existing database/sql tooling and ORMs. It states that the standard interface is slower. When in doubt, the README says to use the native interface.
Which Go versions does clickhouse-go support?
Support depends on the client version. The README's table lists client >= 2.41 against Go 1.24 and 1.25, and client >= 2.29 against Go 1.21 through 1.24. The repository's go.mod declares go 1.25.0.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/clickhouse-clickhouse-go)
Community notes