Open protocol · Apache-2.0Spec 1.0282 conformance tests

    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"}
    }
    1. 01
      Sign in

      POST /warp/v1/auth/token returns a bearer token.

    2. 02
      Open a session

      POST /warp/v1/sessions, with options and transactions of its own.

    3. 03
      Short query

      POST …/statements with Accept: Arrow streams the result in the same response.

    4. 04
      Long 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, Arrow Flight SQL and Quack compared
    Warp SQL 1.0Arrow Flight SQLDuckDB 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.

    Median seconds per test, lower is better
    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), LAN0.1260.1641.48
    Fetch SF10 lineitem (60M rows), LAN0.8430.81516.11
    Fetch 100M narrow rows, LAN0.4530.3905.33
    Load SF1 lineitem, LAN0.5380.600†1.61
    Load SF10 lineitem, LAN2.842.67†9.42
    Fetch SF1 lineitem, WAN (46 ms)0.3831.5112.97
    Load SF1 lineitem, WAN (46 ms)1.111.80†13.80
    Fetch SF10 lineitem, LAN, plaintext0.7460.96213.22
    Load SF10 lineitem, LAN, plaintext2.622.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 more

    libwarpsql 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.

    GitHub

    ADBC driver

    warp-sql-adbc: Go, with Python bindings, loadable by any ADBC driver manager.

    GitHub

    JDBC driver

    warp-sql-jdbc: one jar for Java 17 and later, no gRPC or Netty.

    GitHub

    JavaScript client

    @gizmodata/warp-sql: TypeScript over plain fetch and Arrow JS, for Node, browsers, Deno, Bun and Cloudflare Workers.

    GitHub

    Conformance suite

    Black-box tests that start your server and talk to it only through the protocol; they fail, never skip, without one.

    GitHub

    Warp 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.

    Schedule a demo!powered by Calendly