Back to Blog
    Release
    Philip Moore
    October 21, 2026
    12 min read

    Introducing Hardcharger™: The DuckDB 2.0 Server, Built on the Open Warp SQL Protocol

    Hardcharger is GizmoData's new open-source server for DuckDB 2.0, built on Warp SQL, an open protocol for SQL over HTTP with Apache Arrow results. On one Graviton5 machine it ran 22 queries derived from TPC-H over 1 TB in 42.4 seconds, for about 9 cents of compute, and every feature is included: access control, SSO, mTLS, audit, instrumentation and a built-in web UI. Apache-2.0, no license keys.

    Hardcharger
    Warp SQL
    DuckDB 2.0
    DuckDB
    Apache Arrow
    Open Source
    Benchmark
    Performance
    RBAC
    GizmoData Cloud
    The Hardcharger bull, a blue charging bull with a red database, beside the Hardcharger wordmark and the words: the DuckDB 2.0 server, built on the open Warp SQL protocol. DuckDB 2.0, Warp SQL: HTTP + Arrow, every feature included, Apache-2.0. By GizmoData.

    Hardcharger™ is GizmoData's new open-source server for DuckDB 2.0. It puts DuckDB on the network for every person and application that needs it, and it speaks Warp SQL, an open protocol we wrote that carries SQL over plain HTTP and returns Apache Arrow. On one AWS Graviton5 machine it ran 22 queries derived from TPC-H over 1 TB in 42.4 seconds, about 9 cents of compute. Every feature is included: access control with row policies and masking, single sign-on, mutual TLS, an audit log, instrumentation and a built-in web UI. There are no editions and no license keys, and it is Apache-2.0 open source.

    Hardcharger is the successor to GizmoSQL, written from scratch for DuckDB 2.0. This post explains why we built a new product instead of a GizmoSQL 2.0, what Warp SQL changes, how fast it is (with the caveats), and how to run it in about a minute.

    Try it now: curl https://install.hardcharger.gizmodata.com | sh

    Install Hardcharger →

    Why a new product

    GizmoSQL turned DuckDB, an in-process library, into a server: concurrent sessions, authentication, TLS, and an Arrow Flight SQL endpoint that JDBC, ADBC, BI tools and AI assistants could all reach. Customers run it in production, on their own machines and on GizmoData Cloud. Running it with them taught us three things.

    • The transport was the friction. Arrow Flight SQL runs on gRPC. That means HTTP/2 end to end, gRPC-aware proxies and load balancers, generated code in every client, and no plain browser client. In our own cloud, every reload of a shared proxy sent long-lived gRPC connections a GOAWAY, and their next calls failed.
    • Security belongs in the core. Flight SQL leaves sign-in, sessions and the ownership of handles to each server, so each server has to get them right on its own. We wanted them in the protocol, where no server can forget one.
    • Features shouldn't be gated. GizmoSQL's access control, instrumentation and SSO were Enterprise features behind a license key. Every team that runs a shared DuckDB needs them.

    DuckDB 2.0 was the moment to fix all three at once. Hardcharger is a standalone server on DuckDB 2.0's v2 C API, not a DuckDB extension and not a port of the GizmoSQL code. It took GizmoSQL's test battery as its acceptance bar, not its structure. GizmoSQL keeps its name and its Flight SQL protocol and stays maintained for about six months; Hardcharger takes only its own names (HARDCHARGER_* variables, hardcharger_* functions), so the two never get confused on one machine.

    Warp SQL: SQL over HTTP, results as Arrow

    We kept the best part of Flight SQL, the Apache Arrow columnar format on the wire, and replaced the rest. Warp SQL is an open protocol (Apache-2.0) for running SQL over ordinary HTTP/1.1 and TLS. Results, query parameters and bulk uploads are Arrow IPC streams; control messages are small JSON documents. Version 1.0 is final: from here on it changes only by addition.

    • Short queries are one round trip. One POST runs a statement and streams its rows back in the same response.
    • Long queries survive real networks. Submit, get a handle, poll, and fetch later. A dropped download resumes from the batch where it stopped, and no request has to outlive a proxy timeout.
    • Big results and big uploads go wide. A client can read one large result as several partitions over separate connections at once, and send one bulk load as several parts that commit as a single transaction, all or nothing.
    • It works with what you already run. Any reverse proxy, load balancer or API gateway that passes HTTP passes Warp SQL. So does curl, and so does a browser's fetch.
    • It's described and tested. The protocol has an OpenAPI 3.1 description, which Hardcharger serves at /warp/v1/openapi.json, and a black-box conformance suite of 282 tests tells any implementation whether it follows the spec.

    This is a whole query, with no driver at all:

    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())"

    Results are described as partitions, each with a location. Today a server splits a large result into partitions on itself; tomorrow a distributed engine can point those partitions at other machines without changing the protocol. Warp SQL has its own page at gizmodata.com/warp-sql, and its specification is on GitHub.

    Security in the protocol, not bolted on

    Warp SQL makes the safe behavior the only behavior, so a server built on it can't skip a check.

    • Bearer tokens, never cookies. A browser never sends a Warp SQL credential on its own, so there is no cross-site request forgery to defend against.
    • Every handle is bound to its owner. Sessions, statements, results and uploads belong to the identity that created them and are checked on every use. Guessing another user's handle gets you nothing.
    • Single sign-on on the main port. Browser sign-in with your OpenID Connect provider runs on the server's own port and certificate. The server is the provider's confidential client: the client secret stays on the server, PKCE and a nonce protect the exchange, and each sign-in is collected once, with a secret that is never in a URL.
    • Certificates as identity. Under mutual TLS a client can sign in with its certificate alone. Tokens from a certificate sign-in are bound to that certificate (RFC 8705), so a copied token is useless without the private key, and revocation lists are checked for every certificate in the chain.

    Inside the server, access control is checked inside DuckDB against each statement's own plan, after binding and again before optimizing, so nested SQL, views and macros can't route around a grant. Anything the check can't classify is refused. Credential and system files on the host (SSH keys, cloud credentials, the server's own TLS key) are refused at DuckDB's file-system layer, whoever asks, the administrator included.

    1 TB, all 22 queries derived from TPC-H, in 42.4 seconds

    We ran a workload derived from TPC-H, its 22 queries over 1 TB of data (scale factor 1000), on one AWS r9gd.24xlarge: Graviton5, 96 vCPUs, 742 GiB of memory and three local NVMe disks in RAID 0, on demand at $7.69 an hour. Each query ran three times; the score is the sum of the 22 per-query means. We compare Hardcharger with the earlier GizmoSQL 1.42.0 baseline running DuckDB 1.5.6, on the same machine type.

    A workload derived from TPC-H at 1 TB, not an official TPC-H result: sum of the 22 query means on an AWS r9gd.24xlarge: GizmoSQL 1.42.0 on DuckDB 1.5.6, 77.0 seconds ($0.164); Hardcharger 2.0.0 on DuckDB 2.0.0, 42.4 seconds ($0.090)
    Derived from the TPC-H Benchmark: not an official TPC-H result, and not comparable to published TPC-H Benchmark results. See About this workload.
    • 42.4 seconds for all 22 queries over 1 TB, which costs $0.090 of compute at the on-demand price.
    • 1.8× faster than the earlier GizmoSQL 1.42.0 baseline on DuckDB 1.5.6 (77.0 s).

    Selected per-query means, with the earlier DuckDB 1.5.x baseline for context:

    QueryGizmoSQL 1.42.0 (DuckDB 1.5.6)Hardcharger 2.0.0
    Q0913.34 s5.08 s
    Q2110.83 s2.93 s
    Q142.54 s1.05 s
    Q201.91 s0.87 s
    Q221.67 s0.75 s

    What to keep in mind when reading these numbers:

    • Hardcharger uses DuckDB 2.0.0; the historical GizmoSQL baseline uses DuckDB 1.5.6. The performance difference includes changes in the engine and does not isolate the effect of the server protocol.
    • The Hardcharger client ran on the same machine, over TLS to 127.0.0.1. The answers to these queries are a few rows each, so the network adds little.
    • Cold first runs are included. We dropped the page cache and restarted Hardcharger before each pass. The DuckDB 1.5.6 result is an earlier historical baseline.
    • Defaults only: 96 threads, DuckDB's default memory limit, nothing tuned. A second full pass came within 2% of the first, and every Hardcharger query returned the expected row count.

    About this workload. 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. It is not an official TPC-H result.

    How it differs from TPC-H: we timed only the 22 queries (no refresh functions, no power or throughput test, no TPC-H metric, no audit); the data was generated with tpch-datagen and loaded, untimed, into DuckDB files; each query ran three times back to back over one connection, and we report the sum of the means; Q11's query text uses a fixed fraction (0.0001) rather than 0.0001/SF, so it returns no rows at this scale; and the cost is the cloud's on-demand price for the run time, not TPC pricing.

    TPC-H™ is a trademark of the Transaction Processing Performance Council (TPC).

    Concurrency: 3× the QPS with zero errors

    In ClickBench's concurrency phase, Hardcharger reached 3× the queries per second of GizmoSQL's published ClickBench entry (0.350 vs 0.117 QPS) with zero errors, on the same machine class (c6a.4xlarge); in GizmoSQL's entry, 90% of the concurrent queries failed. Hardcharger 2.0.0-rc.1 dry run (October 20, 2026), pending the GA run.

    Moving data is where Warp SQL shows

    The answers to those queries are small, so they mostly measure the engine. Fetching and loading large results measures the server and the protocol. Between two AWS c8gn.8xlarge machines, with TLS on both servers and the median of five runs:

    WorkloadHardchargerGizmoSQL 1.42Speed-up
    Fetch lineitem at SF10, data derived from TPC-H (60M rows, 10.5 GB of Arrow)0.97 s15.2 s15.7× faster
    Fetch 100M narrow rows0.45 s5.43 s12.0× faster
    Fetch SF1 lineitem across regions (46 ms away)1.96 s12.26 s6.3× faster
    Load SF10 lineitem (bulk ingest, 8 upload parts)3.00 s9.44 s3.1× faster

    Every result travels through an asynchronous pipeline: DuckDB keeps producing 122,880-row Arrow batches while earlier batches are compressed (lz4_frame or zstd when the client asks, on a pool of threads, skipping buffers that wouldn't shrink) and encrypted, and a large result can be read over several connections at once. The method and the full results are in the benchmarks document.

    Every feature included, no license keys

    Everything that was Enterprise in GizmoSQL is in every Hardcharger build, and each feature turns on with its own option:

    • Role-based access control: users, roles, grants down to columns, ownership and system privileges, managed in SQL (CREATE ROLE, GRANT, REVOKE). A revoke reaches open sessions too, and changes reach every replica within about a second. The store is PostgreSQL for production, or a DuckDB file for development and single servers.
    • Row policies, column masking and tenants, per-catalog access rules and Open Policy Agent, plus table functions that answer "who can do what" for each user.
    • Sign-in your way: passwords, tokens, SSO through OIDC/JWKS, browser sign-in, authorized e-mail filters, TLS and mutual TLS.
    • A tamper-evident audit log.
    • Observability: session and statement instrumentation into a DuckDB file or PostgreSQL (the writer keeps up with about 20,000 statements a second on PostgreSQL), catalog logging, query profiles, a Prometheus /metrics endpoint, and hardcharger_active_connections() to see what runs right now.
    • Control: a statement queue, timeouts, KILL SESSION, hardcharger_cancel() and graceful shutdown.
    • DuckDB 2.0 with DuckLake and DuckDB's extensions.
    • Configured your way: flags, HARDCHARGER_* environment variables, or a YAML file.
    • Everywhere you run: Linux (x86-64 and arm64), macOS on Apple silicon and Windows (x64 and arm64, with MSIs), with the macOS and Windows builds code-signed; multi-architecture Docker images; and a Python package that runs the server for you.
    • Drivers: ADBC for Go, Python, C/C++, R and Rust; JDBC for Java and BI tools such as DBeaver; and a JavaScript client for Node, browsers, Deno, Bun and Cloudflare Workers. See the integrations.

    A web UI in the binary

    Hardcharger has a web UI compiled into the server: nothing extra to install, served on the server's own port and certificate. It is off by default; --web-ui turns it on.

    Hardcharger's web UI: the schema browser, SQL editor tabs and a results grid
    The SQL editor: tabs with their own sessions, the schema browser, and a results grid that copies into a spreadsheet as cells.
    • SQL editor with up to 20 tabs, each its own session, transaction and settings. Run the statement at the cursor, the selection or the whole script, with a result tab per result set. An open transaction shows as a badge with Commit and Rollback.
    • Results grid for up to a million rows: sort, filter, resize, select like a spreadsheet, and copy into Excel or Google Sheets as cells, Safari included.
    • Schema browser and autocomplete that follow access control: each user sees only the catalogs, schemas, tables and columns their roles allow.
    • Downloads as CSV, TSV, JSON or Excel, or the whole typed result as Parquet or Arrow; saved queries in folders; and Run as one of your roles.
    • A Sessions page, and an API page: the server's own Warp SQL API in Swagger UI, where Try it out runs against this server, signed in as you.
    • Sign in with a password, your identity provider, or your client certificate.
    The web UI's API page: the server's Warp SQL operations in Swagger UI
    The API page: every Warp SQL operation of this server, from its own OpenAPI document, ready to try.

    Get started in a minute

    On macOS (Apple silicon) or Linux, install the server and the hardcharger command-line client with one line, then start the server with the web UI on:

    curl https://install.hardcharger.gizmodata.com | sh
    HARDCHARGER_ADMIN_PASSWORD='change-me' ~/.hardcharger/bin/hardcharger-server --database my.duckdb --web-ui
    # open http://localhost:31337/ui and sign in as hardcharger / change-me

    Or run the multi-architecture image (linux/amd64, linux/arm64), from GitHub's registry or Docker Hub:

    docker run --rm -p 31337:31337 -p 31338:31338 \
      -e HARDCHARGER_ADMIN_PASSWORD='change-me' -e HARDCHARGER_WEB_UI=true \
      ghcr.io/gizmodata/hardcharger:latest

    Or start one from Python, in a test, notebook or script. The hardcharger package downloads the server for your platform, checks it and runs it; the [adbc] extra adds the client:

    pip install "hardcharger[adbc]"
    1import hardcharger
    2
    3with hardcharger.Server(password="change-me") as server, server.connect() as conn, conn.cursor() as cur:
    4    print(server.uri)  # hardcharger://127.0.0.1:<port>?tls=false
    5    cur.execute(operation="SELECT 42 AS answer")
    6    print(cur.fetch_arrow_table())

    Connect

    The hardcharger client is an interactive shell with history, completion and highlighting, and it runs scripts too. Against a local server without TLS, say --tls=false:

    export HARDCHARGER_PASSWORD='change-me'
    hardcharger --host localhost --tls=false --username hardcharger --quiet <<'SQL'
    CREATE OR REPLACE TABLE trips AS SELECT * FROM (VALUES (1, 'Boston', 12.5), (2, 'Denver', 30.0)) t(id, city, miles);
    SELECT city, miles FROM trips ORDER BY miles DESC;
    SQL
    OK, 2 rows affected
    ┌─────────┬──────────────┐
    │  city   │    miles     │
    │ varchar │ decimal(3,1) │
    ├─────────┼──────────────┤
    │ Denver  │         30.0 │
    │ Boston  │         12.5 │
    ├─────────┴──────────────┤
    │ 2 rows  2 columns      │
    └────────────────────────┘

    From Python, with the ADBC driver (pip install adbc-driver-hardcharger), bind parameters included:

    1from adbc_driver_hardcharger import dbapi as hardcharger
    2
    3with hardcharger.connect(uri="hardcharger://localhost?tls=false", username="hardcharger", password="change-me") as conn:
    4    with conn.cursor() as cur:
    5        cur.execute(operation="SELECT city, miles FROM trips WHERE miles > ?", parameters=[20])
    6        print(cur.fetch_arrow_table())

    From Java, with the JDBC driver, a single jar for Java 17 and later with no gRPC, Netty or protobuf:

    Properties properties = new Properties();
    properties.setProperty("user", "hardcharger");
    properties.setProperty("password", "change-me");
    properties.setProperty("useEncryption", "false"); // plain HTTP on localhost
    try (Connection connection = DriverManager.getConnection("jdbc:hardcharger://localhost", properties);
         ResultSet rows = connection.createStatement().executeQuery("SELECT city, miles FROM trips ORDER BY id")) {
      while (rows.next()) {
        System.out.println(rows.getString("city") + " " + rows.getBigDecimal("miles"));
      }
    }

    The install page covers Windows, the release binaries and the Python package, and the documentation covers every option.

    Coming from GizmoSQL

    Your SQL is DuckDB's in both (check DuckDB's release notes for what changed between 1.x and 2.0), and every option keeps its meaning; what changes is the protocol (Warp SQL instead of Flight SQL, so use the Hardcharger drivers) and the names. The migration guide maps every GizmoSQL flag, environment variable, SQL function, setting, catalog and metric to its Hardcharger name, and the client's options too.

    GizmoSQL 1.x isn't going away overnight: we will keep maintaining it for about six months, so you can move on your own schedule. If you are a GizmoSQL customer, talk to us and we'll help you plan the move.

    The best way to run it: GizmoData Cloud

    Hardcharger is coming to GizmoData Cloud, our fully managed service on AWS, Google Cloud and Azure. You pick a region and a size; we run the clusters, the certificates, the load balancers and the DuckLake catalogs, and you get a server you can connect to from every driver above.

    Run DuckDB without running servers. Start free on GizmoData Cloud.

    Start free on GizmoData Cloud →

    What's next

    • DuckDB 2.0.0 numbers. The same benchmark, every server on the same DuckDB 2.0.0 release.
    • Upload data in the web UI (coming soon): CSV, TSV, Excel, Parquet, JSON or Arrow into a new or existing table, read in the browser and sent over Warp SQL's bulk ingest in one transaction.
    • Hardcharger for iPhone and iPad (coming soon): the server running in the app, with its web UI and a native SQL console, and remote servers with single sign-on.
    • Distributed queries (coming soon): Warp SQL already describes every result as partitions with locations, so one query can be spread across many machines without a protocol change.

    Open source, Apache-2.0

    Hardcharger, Warp SQL, its conformance suite and the drivers are open source under the Apache License 2.0. Star the repository on GitHub, read the product page, and come say hello in the GizmoData Community Slack. We can't wait to see what you build with it.

    Hardcharger™ and GizmoData™ are trademarks of GizmoData LLC. DuckDB is a trademark of the DuckDB Foundation. Apache Arrow is a trademark of the Apache Software Foundation. TPC-H™ is a trademark of the Transaction Processing Performance Council (TPC).

    Ready to Try Hardcharger?

    The DuckDB 2.0 server: open source, on the open Warp SQL protocol, with every feature included

    Schedule a demo!powered by Calendly