- Hardcharger
- Warp SQL
Warp SQL: run SQL from anything that speaks HTTP, get Arrow back
An open protocol for SQL over plain HTTP. Results, parameters and uploads travel as Apache Arrow IPC streams; everything else is small JSON. No gRPC, no protobuf, no generated code. It is the protocol Hardcharger speaks.
A quick look
Three requests with curl, and pyarrow reads the answer. That is the whole client.
# Get a token, open a session, run a query, read the result with pyarrow.
TOKEN=$(curl -s localhost:31337/warp/v1/auth/token -H 'Content-Type: application/json' \
-d '{"grant_type": "password", "username": "hardcharger", "password": "change-me"}' | jq -r .access_token)
SESSION=$(curl -s localhost:31337/warp/v1/sessions -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{}' | jq -r .session_id)
curl -s localhost:31337/warp/v1/sessions/$SESSION/statements -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -H 'Accept: application/vnd.apache.arrow.stream' \
-d '{"sql": "SELECT 42 AS answer"}' > result.arrows
python -c "import pyarrow.ipc as ipc; print(ipc.open_stream(source='result.arrows').read_all())"Every server describes itself
GET /warp lists the protocol versions, capabilities and sign-in methods a server supports, so a client knows what it may use. Here, Hardcharger:
{
"protocol": "warp-sql",
"protocol_versions": ["1"],
"server": {"name": "Hardcharger", "version": "2.0.0 (DuckDB v2.0.0)"},
"capabilities": ["prepared_statements", "transactions", "ingest", "partitioned_ingest",
"long_poll", "ipc_compression_zstd", "ipc_compression_lz4_frame",
"result_partitions", "openapi"],
"auth": {"grant_types": ["password"]},
"links": {"openapi": "/warp/v1/openapi.json"}
}- 01Sign in
POST /warp/v1/auth/token returns a bearer token.
- 02Open a session
POST /warp/v1/sessions, with options and transactions of its own.
- 03Short query
POST …/statements with Accept: Arrow streams the result in the same response.
- 04Long query
Prefer: respond-async returns a handle; long-poll it, then GET …/result?from_batch=N, resumable.
Anything that speaks HTTP
A browser fetch, curl, or any language’s standard HTTP library. No gRPC, no protobuf, no generated code, and nothing a proxy or firewall needs to learn.
Arrow on the wire
Results, query parameters and bulk uploads are Arrow IPC streams (application/vnd.apache.arrow.stream), so every Arrow library reads them directly. Control messages are small JSON documents.
Short queries stay one round trip
One POST runs a query and streams its result back in the same response.
Big results go wide
A client can ask for a large result as several partitions and read them over separate connections at once, past what one TCP stream carries, with the order kept when the query has one.
Big uploads go wide too
Streaming bulk ingest, sent as several parts over separate connections and committed as one transaction: all or nothing. Arrow buffers can travel lz4_frame or zstd compressed, negotiated by preference.
Long queries survive real networks
Submit a query, get a handle, long-poll it and fetch the result later. A dropped download resumes from the batch where it stopped, and no request has to outlive a proxy timeout.
Security in the core
Credentials are bearer tokens, never cookies, so there is no CSRF to defend. Every session, statement and result handle is bound to the identity that created it and checked on every use; results and metadata follow the caller’s authorization. Token sign-in, token exchange, browser sign-in and client certificates are in the spec.
Bind parameters
Positional and named parameters on statements, and prepared statements that take JSON or Arrow parameter batches: values travel as values, never spliced into SQL text.
OpenAPI 3.1, served by every server
GET /warp/v1/openapi.json describes the API for API browsers and client generators, and GET /warp lists what this server supports.
A conformance suite
A 282-test black-box suite talks to a server only through the protocol, so any implementation can prove it conforms.
Driver code carries over
Metadata answers use Arrow Flight SQL’s result schemas, so catalog, schema and table listings look the same to driver code.
Ready to scale out
Results are described as partitions, each with a location. Today a server splits a result on itself; a distributed engine can point partitions at other machines without changing the protocol.
Warp SQL vs Arrow Flight SQL vs Quack
Arrow Flight SQL is the Apache Arrow project’s SQL protocol on gRPC. Quack is DuckDB Labs’ protocol for one DuckDB to attach another. Warp SQL keeps Arrow on the wire and moves everything else to plain HTTP.
| Warp SQL 1.0 | Arrow Flight SQL | DuckDB Quack | |
|---|---|---|---|
| Transport | Plain HTTP/1.1, with TLS | Arrow Flight RPC, built on gRPC; commands are Protobuf messages | DuckDB’s own protocol over HTTP/1.1 |
| Result format | Arrow IPC streams | Arrow IPC | DuckDB’s own format |
| What a client needs | Any HTTP client: fetch, curl, a standard library | A Flight (gRPC) client library or driver | DuckDB with the quack extension (CLI, a DuckDB library, or DuckDB-Wasm) |
| Browsers | Plain fetch, CORS for allowed origins | Through DuckDB-Wasm | |
| API description | Written spec, plus OpenAPI 3.1 served by every server | Protobuf definitions in the Apache Arrow format docs | PartialMessages defined in the extension’s source; no separate spec found |
| Conformance suite | 282 black-box tests | None found | |
| Stability | 1.0: changes only by addition, so a 1.0 client keeps working | Part of Apache Arrow; the metadata set may expand | Version 3 in DuckDB 2.0; DuckDB’s docs say it may still change |
| Security model in the protocol | Bearer tokens (no cookies), handles bound to their principal, governed results; password, token exchange, browser sign-in, mTLS | PartialOne shared token by default, or your own SQL function; no client certificates | |
| Bind parameters | Positional and named; JSON or Arrow parameter batches | Prepared statements, parameters bound with DoPut | SQL text only |
| Long-running queries | Submit, long-poll, fetch later | PollFlightInfo | |
| Resume a dropped download | From the batch where it stopped | ||
| Parallel (partitioned) results | Partitions read over several connections, in order when asked | Endpoints, each with locations, consumable in parallel | |
| Bulk ingest | Streaming, in parallel parts, committed atomically | CommandStatementIngest | Into an attached database |
| Compression | lz4_frame or zstd, negotiated by preference | ||
| Cancellation | Statement and session | CancelFlightInfo | quack_cancel() |
| License | Apache-2.0 | Apache-2.0 (Apache Arrow) | MIT |
Sources: the Warp SQL specification; the Apache Arrow docs for Flight SQL and Flight; DuckDB’s Quack docs and our checks on running servers (Quack e7a9be3f8c, the commit DuckDB 2.0 pins). A dash means we have no verified source for that cell, not that the feature is missing; individual Flight SQL servers may add more.
Measured over a real network
Three DuckDB servers, each with its default client, moving lineitem tables (data derived from TPC-H, generated with dbgen) and a 100-million-row table between AWS machines. Hardcharger over Warp SQL was 3 to 34 times faster than GizmoSQL over Arrow Flight SQL in every test, and faster than Quack in five of nine.
| Test (median seconds, lower is better) | Warp SQL Hardcharger | Quack DuckDB 2.0 attach | Arrow Flight SQL GizmoSQL 1.42.0 |
|---|---|---|---|
| Fetch SF1 lineitem (6M rows), LAN | 0.126 | 0.164 | 1.48 |
| Fetch SF10 lineitem (60M rows), LAN | 0.843 | 0.815 | 16.11 |
| Fetch 100M narrow rows, LAN | 0.453 | 0.390 | 5.33 |
| Load SF1 lineitem, LAN | 0.538 | 0.600† | 1.61 |
| Load SF10 lineitem, LAN | 2.84 | 2.67† | 9.42 |
| Fetch SF1 lineitem, WAN (46 ms) | 0.383 | 1.51 | 12.97 |
| Load SF1 lineitem, WAN (46 ms) | 1.11 | 1.80† | 13.80 |
| Fetch SF10 lineitem, LAN, plaintext | 0.746 | 0.962 | 13.22 |
| Load SF10 lineitem, LAN, plaintext | 2.62 | 2.60† | 9.46 |
How we measured (2026-10-19): AWS c8gn.8xlarge machines (Graviton4, 32 vCPU, 100 Gbit/s), server and client in one placement group (LAN) or the client in another region about 46 ms away (WAN); TLS on every server unless the row says plaintext; threads=32 and memory_limit=40GB on every server; median of five runs after a warm-up, every load checked against the source. Clients: the Warp SQL ADBC driver with its default settings, adbc-driver-gizmosql for GizmoSQL, and DuckDB’s own client attaching Quack.
These compare whole servers, not protocols alone: Hardcharger and Quack ran the same DuckDB 2.0 pre-release build, GizmoSQL ran DuckDB 1.5.6. † Quack without insertion order (its default keeps it, and was slower: 1.016 s for the LAN SF1 load, 2.684 s over the WAN); Hardcharger’s parallel upload parts keep no row order either. Quack was faster on the large LAN fetches (by 3% and 16%) and the large LAN loads (by 6%, and by 1% without TLS).
Scale factors SF1 and SF10 refer to that generated data. This workload is derived from the TPC-H Benchmark and is not comparable to published TPC-H Benchmark results, as this implementation does not comply with all requirements of the TPC-H Benchmark. TPC, TPC Benchmark and TPC-H are trademarks of the Transaction Processing Performance Council (TPC).
Full results, including CPU use and bytes on the wire: benchmark notes.
Implementations
Hardcharger™
GizmoData’s DuckDB 2.0 server. It passes GizmoSQL’s test battery over Warp SQL alone.
Learn morelibwarpsql and warp-duckdb
A C++20 server SDK (engines implement a backend; the SDK owns sign-in, handle binding, retention, cancellation and streaming) and a reference server for testing.
GitHubJavaScript client
@gizmodata/warp-sql: TypeScript over plain fetch and Arrow JS, for Node, browsers, Deno, Bun and Cloudflare Workers.
GitHubConformance suite
Black-box tests that start your server and talk to it only through the protocol; they fail, never skip, without one.
GitHubWarp SQL FAQ
What is Warp SQL?
Warp SQL is an open protocol (Apache-2.0) that lets any HTTP client run SQL against a database server and get Apache Arrow data back: a browser fetch, curl, or any language’s HTTP library. Results, parameters and uploads are Arrow IPC streams; control messages are small JSON documents. Hardcharger, GizmoData’s DuckDB 2.0 server, speaks it.
How is Warp SQL different from Arrow Flight SQL?
Both carry Arrow record batches. Arrow Flight SQL runs on gRPC with Protobuf messages and needs a Flight client library; Warp SQL is plain HTTP and JSON, so anything that can make an HTTP request is a client, including a browser. Warp SQL also puts resumable downloads, a security model with handles bound to their owner, and an OpenAPI description served by every server into the protocol, and it borrows Flight SQL’s metadata schemas so driver code carries over.
Is Warp SQL faster than Arrow Flight SQL?
In our measurements on AWS (2026-10-19), Hardcharger over Warp SQL with its ADBC driver moved results and loads 3 to 34 times faster than GizmoSQL 1.42.0 over Arrow Flight SQL, across nine fetch and load tests. Those compare whole servers, including different DuckDB versions, not the two protocols alone. Against DuckDB’s Quack, Hardcharger was faster in five of the nine tests and slower in four.
Which servers and clients speak Warp SQL?
Server: Hardcharger, plus warp-duckdb, the reference server for testing. Clients: the Warp SQL ADBC driver (Go, with Python bindings, loadable by any ADBC driver manager), a JDBC driver for Java 17 and later, a JavaScript client for Node, browsers, Deno, Bun and Cloudflare Workers, and any HTTP client.
Can I implement Warp SQL for my own engine?
Yes. The spec, its OpenAPI description and the conformance suite are Apache-2.0, and libwarpsql, a C++20 server SDK, handles authentication, handle binding, retention, cancellation and the streaming pipeline while your engine implements a backend. Run the conformance suite against your server to check it.
Will Warp SQL 1.0 change under me?
Version 1 is stable: it changes only by addition (new endpoints, fields, capabilities and error codes), so a client written for 1.0.0 keeps working. New features arrive behind capabilities that a server lists at GET /warp.
Try Warp SQL in a minute
Install Hardcharger, start it, and point curl at port 31337. Or read the spec and build your own server.
Warp SQL is an independent project; it is not part of, or endorsed by, the Apache Software Foundation. Apache Arrow, Arrow and Apache are trademarks of The Apache Software Foundation. Hardcharger™ and GizmoData™ are trademarks of GizmoData LLC.