Skip to main content

thunderduck-sqlalchemy

A SQLAlchemy dialect and PEP 249 DBAPI for thunderduck. Query your lakehouse from anything that speaks SQLAlchemy — Superset, Airflow, Dagster, Redash, pandas, Jupyter, Streamlit.

pip install thunderduck-sqlalchemy

Works with SQLAlchemy 1.4 and 2.x, on Python 3.10+ — so it installs cleanly into Apache Superset (which pins SQLAlchemy 1.4) as well as modern Airflow, Dagster and pandas environments.

Connect

Create an API token in the thunderduck console (Settings → API Tokens; it starts with tdk_ and is shown once), then:

from sqlalchemy import create_engine, text
from sqlalchemy.pool import NullPool

engine = create_engine(
    "thunderduck://:tdk_your_token@api.thunderduck.io/",
    poolclass=NullPool,
)

with engine.connect() as conn:
    for row in conn.execute(
        text('SELECT * FROM "tndr_postgres_demo"."ecommerce"."orders" LIMIT 10')
    ):
        print(row)

pandas works directly:

import pandas as pd

df = pd.read_sql('SELECT * FROM "thunder_duck_demo"."iris"', engine)

URL options

Option Default Meaning
password / ?token= — Required. Your tdk_… API token.
?ssl=false true Use plain HTTP. For in-cluster use against the console-api Service.
?poll_ms= 1000 How often to poll for completion.
?timeout_ms= 300000 How long to wait for a query.
?arraysize= 1000 Rows fetched per page.

Table names

thunderduck names are catalog.schema.table (flat-file catalogs) or catalog.table (Iceberg/Nessie catalogs). SQLAlchemy models two levels, so the schema is the whole dotted prefix:

from sqlalchemy import MetaData, Table

md = MetaData()
orders = Table("orders", md, schema="tndr_postgres_demo.ecommerce", autoload_with=engine)  # 3-level
iris = Table("iris", md, schema="tndr_glue_demo", autoload_with=engine)  # 2-level

Reflection (inspect(engine).get_schema_names() etc.) reads thunderduck's catalog API rather than issuing SQL, so browsing schemas is fast and free.

Apache Superset

Installing the package is all that is needed — it registers a Superset DB engine spec automatically. Add a database of type Other with:

thunderduck://:tdk_your_token@api.thunderduck.io/

Superset's stop button genuinely cancels the running query.

How it works, and what follows from that

Every statement is submitted to thunderduck's REST API, which runs it as an isolated Kubernetes Job; results are then paged back over HTTP. That model has consequences worth knowing up front:

  • Latency. Expect seconds, not milliseconds, before the first row. Built for analytics and BI, not for tight interactive loops.
  • Read-only. No DML, no DDL, no transactions. commit() and rollback() are no-ops.
  • Use NullPool. A connection holds no server-side state, so pooling buys nothing. The driver also never issues a SELECT 1 health check, because that would start a whole Job.
  • Parameters are rendered client-side. thunderduck's API accepts SQL only, so this driver renders bound parameters into the statement, escaping them strictly and refusing types it does not recognise. Always pass untrusted values as parameters — never build SQL by string concatenation. The paramstyle is pyformat, so — as with psycopg2 — a literal percent sign in hand-written SQL must be escaped as %% when you pass parameters.
  • Row ceiling. The server caps how many rows one page returns and how many a result set stores. Very large result sets are truncated; aggregate in SQL rather than pulling raw rows.

Also available

For JVM tools (DBeaver, DataGrip) there is a JDBC driver — see the jdbc-driver/ directory of the thunderduck repository.

Development

uv sync --dev
uv run pytest
uv run ruff check . && uv run ruff format --check .

One gotcha: the committed uv.lock resolves SQLAlchemy 2.x, so a plain uv run pytest only exercises one of the two supported majors. Apache Superset pins sqlalchemy<2, so check that combination too before releasing:

uv venv --python 3.10 .sa14
uv pip install --python .sa14 -e . "sqlalchemy<2" pytest
.sa14/bin/python -c "import sqlalchemy; print('SQLALCHEMY', sqlalchemy.__version__)"
.sa14/bin/pytest -q

CI runs both legs on every push.

License

Apache-2.0

Metadata

Release files for thunderduck-sqlalchemy 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for thunderduck-sqlalchemy 1.0.1
File Size Uploaded
thunderduck_sqlalchemy-1.0.1.tar.gz 20.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for thunderduck-sqlalchemy 1.0.1
File Interpreter ABI Platform
thunderduck_sqlalchemy-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 45.5 kB

Release files / thunderduck_sqlalchemy-1.0.1.tar.gz

Download URL thunderduck_sqlalchemy-1.0.1.tar.gz
Size 20.4 kB
Tags Source
SHA-256 checksum
How to use checksums
7a95b5e4f40e6e440942b85643f3e9519d08adf3fca3af5ce7a61c42e0fc4f71
BLAKE2b-256 checksum
How to use checksums
0511658990374a243f62f42feab7683f8f9254a067d683b0f187d8b72fb9d66a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.

Transparency log

Release files / thunderduck_sqlalchemy-1.0.1-py3-none-any.whl

Download URL thunderduck_sqlalchemy-1.0.1-py3-none-any.whl
Size 25.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f640be5ed37bd5a68324f5256fe2f34a16ee4a44e6fd54df7493bfe2162ecc47
BLAKE2b-256 checksum
How to use checksums
873660a6c59794df14db41668eda70686551f50d648147848e210555cf56a5ac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page