# turbodbc moves database rows in batches and hands back NumPy arrays

> turbodbc is a C++ backed Python module that speaks ODBC while complying with PEP 249, returning NumPy and Apache Arrow results and using batched data transfer instead of the single-record communication that other ODBC modules rely on.

**blue-yonder/turbodbc** — Turbodbc is a Python module to access relational databases via the Open Database Connectivity (ODBC) interface. The module complies with the Python Database API Specification 2.0.

- Repository: https://github.com/blue-yonder/turbodbc
- Website: http://turbodbc.readthedocs.io/en/latest
- Stars: 659 · Forks: 83
- Language: C++
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/blue-yonder-turbodbc

## The audience is stated in the first paragraph

Turbodbc bills itself as turbocharged database access for data scientists, and the README is unusually precise about who that means. It is a Python module to access relational databases through the Open Database Connectivity interface, and its primary target audience is data scientists who use databases for which no efficient native Python drivers are available.

That sentence defines both the opportunity and the boundary. If your database has a good native Python driver, the ODBC route is an extra layer of translation, and a native driver is the better answer. If it does not, and the only thing available is an ODBC driver, then something has to sit between your pandas script and the database, and turbodbc is built to be that something without asking you to leave the Python data stack.

The project is not a general database framework. It is a driver, and it behaves like one. It is free to use under the MIT licence, open source on GitHub, and available for Linux, macOS and Windows.

It is also worth noticing what the README does not claim. There is no throughput number, no benchmark table and no comparison against a named alternative in the text. The claim is structural instead: turbodbc internally relies on batched data transfer instead of single-record communication as other popular ODBC modules do. That is a statement about the transport, and it is the whole thesis.

## PEP 249 is the contract that keeps the pandas stack working

Turbodbc complies with the Python Database API Specification 2.0, PEP 249, and the README states the reason: maximum compatibility.

That choice is what makes the module a drop-in rather than a new API. Code written against a DB API 2.0 driver, including the pandas read_sql path and a large amount of existing analysis code, works against turbodbc without rewriting the calls. The connection object, the cursor, the execute and fetchmany sequence, the parameter binding and the description metadata all follow the specification, so a tool that speaks DB API does not need to know which driver is underneath it.

This matters more than it first appears, because the alternative to turbodbc is not writing your own wrapper. Anyone in that position is likely to reach for an existing ODBC module in Python, and the difference between them is exactly the axis the README names: other popular ODBC modules communicate one record at a time, while turbodbc uses batched data transfer. The same loop over a cursor, the same fetchmany call, a different amount of work per row.

The repository topics list includes pep249 and python-database-api, alongside numpy, odbc, pyodbc and exasol, which reads like the project's own positioning: a specification-conformant ODBC driver aimed at the scientific Python stack, with the volume of data as the reason to exist.

## A C++ core behind a Python module, and why that shape

Turbodbc is written as a native extension. The primary language in the repository is C++, with a cpp directory at the top level and the Python package in a turbodbc directory, and the build is driven by Meson through the meson-python backend, with pybind11 doing the binding work.

That architecture is what makes the batched transfer and the array output possible at the same time. A pure Python driver that asks the ODBC library for one row at a time pays the round trip cost in Python, and the resulting data has to be assembled into Python objects before anything can be done with it. A native layer can request a whole batch from the driver manager, move it across the boundary once, and expose it as a buffer rather than a tuple.

The array support is the visible part of that. The README names built-in NumPy and Apache Arrow support, and the build requirements pull in numpy and pyarrow, with pyarrow pinned below version 25 and numpy at 2 or later. The result of a fetch can therefore be a numeric array or an Arrow table, which means the data lands in the form the rest of a scientific workflow wants it in, instead of being a column of Python scalars that has to be converted afterwards.

The repository layout backs up the hybrid shape. There is a cpp directory, a tests directory, a meson.build and meson.options at the top level, separate odbc_test_linux and odbc_test_osx directories, and a performance_scripts directory, so the project carries its own benchmarks, though the README does not publish their results.

## Installing the built wheel and what the build pulls in

The packaging metadata is where the installation story lives, and it is a modern one. The build backend is mesonpy, and the build requirements are declared explicitly:

```toml
[build-system]
requires = [
    "pyarrow>=18,<25",
    "pybind11",
    "numpy>=2",
    "meson>=1.0.0",
    "meson-python>=0.14.0",
]
build-backend = "mesonpy"
```

Those requirements are what a source build needs: a Meson toolchain of at least 1.0, the Meson Python backend, pybind11 for the bindings, and NumPy and pyarrow for the array types. A user installing a published wheel does not need a compiler, but a user building from source does, along with an ODBC driver manager on the host.

The project metadata gives the rest. The version is 5.3.0, the licence is MIT, and the classifiers mark the development status as Production/Stable. The operating system classifiers cover Linux, macOS and Windows, matching the README, and the Python classifiers list 3.11, 3.12, 3.13 and 3.14. The requires-python field says 3.11 or later.

That last point is a discrepancy worth checking rather than assuming. The README says turbodbc works with Python 3.9 and later, while the packaging metadata requires 3.11 and above and lists only 3.11 through 3.14. The metadata is what the installer enforces, so on Python 3.9 or 3.10 the install will fail or refuse to resolve. If you are on an older interpreter, the pip resolver is the authority and the README text is out of date.

The README points to the documentation at turbodbc.readthedocs.io for the install instructions, and the project is also packaged on conda-forge, which is the practical route for environments where a compiler and an ODBC driver manager are awkward to arrange.

## What it does not solve for you

The honest limitations are structural, and they follow from the design rather than from a missing feature.

The first is that turbodbc does not remove the ODBC dependency, it depends on it. It is a bridge to a database through the ODBC interface, so the machine still needs an ODBC driver manager and a driver for the database in question. If the reason you were considering turbodbc was to avoid installing database drivers, this is the wrong tool. The problem it solves is the absence of an efficient native Python driver, not the absence of any driver.

The second is that the batched design changes the shape of interactive use. Fetching a large result set is the case the module is built for. A workload that issues many small queries and reads a row at a time is the case that the batched path does not help, and the README's contrast with single-record communication in other ODBC modules is a warning in that direction as much as a claim about speed.

The third is scope. The documentation is the source for how to install and use the module, and the README itself defers to it, so the details of parameter binding, type handling and error behaviour live in the Sphinx documentation rather than in the repository. The Makefile in the repository is for building that documentation, with the usual set of Sphinx targets.

None of these are defects. They are the shape of a driver, and they are the questions to answer before adding a native extension to a dependency list.

## Testing against real databases, and the project tooling

Turbodbc is routinely tested with MySQL, PostgreSQL, EXASOL and MSSQL, and the README adds that it probably also works with your database. The last clause is a statement about the breadth of ODBC itself rather than a claim about coverage, and it is worth reading with that in mind: an untested combination of driver manager, driver version and database version is where surprises live.

The repository shows how the testing is organised. There is a top-level tests directory, and separate odbc_test_linux and odbc_test_osx directories, which suggests that the parts of the stack that differ by platform have their own fixtures, and that a real ODBC stack is part of the test environment rather than a mocked one. The CI badge points at a GitHub Actions workflow, and codecov is configured, so coverage is measured on every run.

The development tooling is modern and opinionated. The project uses Meson for the build, Black with a target version of py311 for formatting, isort with a known first-party package of turbodbc, and mypy with strict equality, checked untyped definitions and no implicit optionals. There is a pre-commit configuration, a flake8 configuration, and pixi.toml with a pixi.lock for reproducible development environments. The CHANGELOG is kept as CHANGELOG.rst.

For a user, the practical significance is that this is a project with real engineering discipline around it, which matters more for a native extension than for a pure Python package, because a compiler error in a user's environment is a much worse first experience than an import error.

## Release cadence, licence and what to check first

The version history is steady rather than fast. The recent releases are 5.3.0 on 2026-07-01, 5.2.0 on 2026-02-04 and 5.1.2 on 2025-01-18, so the 5.x line has produced a minor release every few months and a patch release in between. The last push to the repository was on 2026-10-20, which is recent work beyond the last tagged release.

The licence is MIT, with the LICENSE file in the repository, so embedding turbodbc in an internal data platform carries the usual attribution obligation and nothing more. There is no copyleft obligation on code that links against it, and no separate licence for the bundled ODBC headers or drivers, which remain the responsibility of whoever installs them.

For an adopter, four checks come before anything else. Confirm an ODBC driver manager and a driver for your database are present on the machine, since turbodbc needs both. Check the Python version against the packaging metadata rather than the README, since the metadata requires 3.11 and the README text still mentions 3.9. Decide whether you need the array path at all, because the NumPy and Arrow support is the feature that justifies the native extension, and a pure Python ODBC module is simpler if you only need plain rows. And read the documentation at turbodbc.readthedocs.io, which is where the install instructions for each platform actually live.

## Conclusion

turbodbc fits a data scientist who has to pull a large result set out of a database through an ODBC driver, and who wants the rows to arrive as NumPy or Arrow objects rather than as a stream of tuples. It is the wrong choice if a native driver already exists for your database, since the ODBC layer it wraps would only add overhead, and it is the wrong choice if you want a single-row interactive cursor, because the batched design is the point rather than an optimisation you can turn off. Before adopting it, confirm that an ODBC driver and driver manager are installed on the host, check the Python version you need against the packaging metadata, which requires 3.11 or later even though the README still says 3.9, and read the documentation at turbodbc.readthedocs.io for the install path that matches your platform.

## FAQ

### What is turbodbc and who is it for?

Turbodbc is a Python module that accesses relational databases through the ODBC interface and complies with the Python Database API Specification 2.0, PEP 249. Its primary audience is data scientists working with databases that have no efficient native Python driver.

### How is turbodbc different from other Python ODBC modules?

The README states that turbodbc internally relies on batched data transfer instead of the single-record communication other popular ODBC modules use, and it offers built-in NumPy and Apache Arrow support so results arrive as arrays rather than as individual values.

### Which Python versions does turbodbc support?

The packaging metadata requires Python 3.11 or later and the classifiers list 3.11 through 3.14, while the README still says the project works with Python 3.9 and later. The metadata is what the installer enforces.

### What does turbodbc need installed on the machine?

It talks to databases through ODBC, so an ODBC driver manager and a driver for the database are required on the host, and turbodbc is also packaged on conda-forge. The documentation at turbodbc.readthedocs.io covers the install steps for each platform.

### Which databases is turbodbc tested against?

The README says it is routinely tested with MySQL, PostgreSQL, EXASOL and MSSQL, and that it probably also works with other databases since it goes through the ODBC interface.

## Sources

- [blue-yonder/turbodbc on GitHub](https://github.com/blue-yonder/turbodbc)
- [License: MIT](https://github.com/blue-yonder/turbodbc/blob/master/LICENSE)
- [Project website](http://turbodbc.readthedocs.io/en/latest)
- [README](https://github.com/blue-yonder/turbodbc/blob/master/README.md)
- [Releases](https://github.com/blue-yonder/turbodbc/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/blue-yonder-turbodbc
