Skip to main content

A high-performance async Python library for Microsoft SQL Server built on Rust for heavy workloads and low latency.

Project description

FastMSSQL ⚡

FastMSSQL is an async Python library for Microsoft SQL Server (MSSQL), built in Rust. Unlike standard libaries, it uses a native SQL Server client—no ODBC required—simplifying installation on Windows, macOS, and Linux. Great for data ingestion, bulk inserts, and large-scale query workloads.

Python Versions

License

Unit Tests

Latest Release

Platform

Rust Backend

Features

  • High performance: optimized for very high RPS and low overhead
  • Rust core: memory‑safe and reliable, tuned Tokio runtime
  • No ODBC: native SQL Server client, no external drivers needed
  • Connection pooling: bb8‑based, smart defaults (default max_size=10, min_idle=2)
  • Async first: clean async/await API with async with context managers
  • Strong typing: fast conversions for common SQL Server types
  • Thread‑safe: safe to use in concurrent apps
  • Cross‑platform: Windows, macOS, Linux
  • Batch operations: high-performance bulk inserts and batch query execution

Key API methods

Core methods for individual operations:

  • query() — SELECT statements that return rows
  • execute() — INSERT/UPDATE/DELETE/DDL that return affected row count
# Use query() for SELECT statements
result = await conn.query("SELECT * FROM users WHERE age > @P1", [25])
rows = result.rows()

# Use execute() for data modification
affected = await conn.execute("INSERT INTO users (name) VALUES (@P1)", ["John"])

Installation

From PyPI (recommended)

pip install fastmssql

Prerequisites

  • Python 3.10 to 3.14
  • Microsoft SQL Server (any recent version)

Quick start

Basic async usage

import asyncio
from fastmssql import Connection

async def main():
    conn_str = "Server=localhost;Database=master;User Id=myuser;Password=mypass"
    async with Connection(conn_str) as conn:
        # SELECT: use query() -> rows()
        result = await conn.query("SELECT @@VERSION as version")
        for row in result.rows():
            print(row['version'])

        # Pool statistics (tuple: connected, connections, idle, max_size, min_idle)
        connected, connections, idle, max_size, min_idle = await conn.pool_stats()
        print(f"Pool: connected={connected}, size={connections}/{max_size}, idle={idle}, min_idle={min_idle}")

asyncio.run(main())

Explicit Connection Management

When not utilizing Python's context manager (async with), FastMssql uses lazy connection initialization:
if you call query() or execute() on a new Connection, the underlying pool is created if not already present.

For more control, you can explicitly connect and disconnect:

import asyncio
from fastmssql import Connection

async def main():
    conn_str = "Server=localhost;Database=master;User Id=myuser;Password=mypass"
    conn = Connection(conn_str)

    # Explicitly connect
    await conn.connect()
    assert await conn.is_connected()

    # Run queries
    result = await conn.query("SELECT 42 as answer")
    print(result.rows()[0]["answer"])  # -> 42

    # Explicitly disconnect
    await conn.disconnect()
    assert not await conn.is_connected()
    
asyncio.run(main())

Usage

Connection options

You can connect either with a connection string or individual parameters.

  1. Connection string
import asyncio
from fastmssql import Connection

async def main():
    conn_str = "Server=localhost;Database=master;User Id=myuser;Password=mypass"
    async with Connection(connection_string=conn_str) as conn:
        rows = (await conn.query("SELECT DB_NAME() as db")).rows()
        print(rows[0]['db'])

asyncio.run(main())
  1. Individual parameters
import asyncio
from fastmssql import Connection

async def main():
    async with Connection(
        server="localhost",
        database="master",
        username="myuser",
        password="mypassword"
    ) as conn:
        rows = (await conn.query("SELECT SUSER_SID() as sid")).rows()
        print(rows[0]['sid'])

asyncio.run(main())

Note: Windows authentication (Trusted Connection) is currently not supported. Use SQL authentication (username/password).

Working with data

import asyncio
from fastmssql import Connection

async def main():
    async with Connection("Server=.;Database=MyDB;User Id=sa;Password=StrongPwd;") as conn:
        # SELECT (returns rows)
        users = (await conn.query(
            "SELECT id, name, email FROM users WHERE active = 1"
        )).rows()
        for u in users:
            print(f"User {u['id']}: {u['name']} ({u['email']})")

        # INSERT / UPDATE / DELETE (returns affected row count)
        inserted = await conn.execute(
            "INSERT INTO users (name, email) VALUES (@P1, @P2)",
            ["Jane", "jane@example.com"],
        )
        print(f"Inserted {inserted} row(s)")

        updated = await conn.execute(
            "UPDATE users SET last_login = GETDATE() WHERE id = @P1",
            [123],
        )
        print(f"Updated {updated} row(s)")

asyncio.run(main())

Parameters use positional placeholders: @P1, @P2, ... Provide values as a list in the same order.

Batch operations

For high-throughput scenarios, use batch methods to reduce network round-trips:

import asyncio
from fastmssql import Connection

async def main_fetching():
    # Replace with your actual connection string
    async with Connection("Server=.;Database=MyDB;User Id=sa;Password=StrongPwd;") as conn:
        
        # --- 1. Prepare Data for Demonstration ---
        columns = ["name", "email", "age"]
        data_rows = [
            ["Alice Johnson", "alice@example.com", 28],
            ["Bob Smith", "bob@example.com", 32],
            ["Carol Davis", "carol@example.com", 25],
            ["David Lee", "david@example.com", 35],
            ["Eva Green", "eva@example.com", 29]
        ]
        await conn.bulk_insert("users", columns, data_rows)

        # --- 2. Execute Query and Retrieve the Result Object ---
        print("\n--- Result Object Fetching (fetchone, fetchmany, fetchall) ---")
        
        # The Result object is returned after the awaitable query executes.
        result = await conn.query("SELECT name, age FROM users ORDER BY age DESC")
        
        # fetchone(): Retrieves the next single row synchronously.
        oldest_user = result.fetchone() 
        if oldest_user:
            print(f"1. fetchone: Oldest user is {oldest_user['name']} (Age: {oldest_user['age']})")
        
        # fetchmany(2): Retrieves the next set of rows synchronously.
        next_two_users = result.fetchmany(2)
        print(f"2. fetchmany: Retrieved {len(next_two_users)} users: {[r['name'] for r in next_two_users]}.")
        
        # fetchall(): Retrieves all remaining rows synchronously.
        remaining_users = result.fetchall()
        print(f"3. fetchall: Retrieved all {len(remaining_users)} remaining users: {[r['name'] for r in remaining_users]}.")
        
        # Exhaustion Check: Subsequent calls return None/[]
        print(f"4. Exhaustion Check (fetchone): {result.fetchone()}")
        print(f"5. Exhaustion Check (fetchmany): {result.fetchmany(1)}")

        # --- 3. Batch Commands for multiple operations ---
        print("\n--- Batch Commands (execute_batch) ---")
        commands = [
            ("UPDATE users SET last_login = GETDATE() WHERE name = @P1", ["Alice Johnson"]),
            ("INSERT INTO user_logs (action, user_name) VALUES (@P1, @P2)", ["login", "Alice Johnson"])
        ]
        
        affected_counts = await conn.execute_batch(commands)
        print(f"Updated {affected_counts[0]} users, inserted {affected_counts[1]} logs")
        
asyncio.run(main_fetching())

Connection pooling

Tune the pool to fit your workload. Constructor signature:

from fastmssql import PoolConfig

# PoolConfig(max_size=10, min_idle=2, max_lifetime_secs=None, idle_timeout_secs=None, connection_timeout_secs=30)
config = PoolConfig(
    max_size=20,              # max connections in pool
    min_idle=5,               # keep at least this many idle
    max_lifetime_secs=3600,   # recycle connections after 1h
    idle_timeout_secs=600,    # close idle connections after 10m
    connection_timeout_secs=30
)

Presets:

one.  = PoolConfig.one()                     # ~ max_size=1, min_idle=1
low   = PoolConfig.low_resource()            # ~ max_size=3,   min_idle=1
dev   = PoolConfig.development()             # ~ max_size=5,   min_idle=1
high  = PoolConfig.high_throughput()         # ~ max_size=50,  min_idle=15
maxp  = PoolConfig.performance()             # ~ max_size=100, min_idle=30

Apply to a connection:

async with Connection(conn_str, pool_config=high) as conn:
    rows = (await conn.query("SELECT 1 AS ok")).rows()

Default pool (if omitted): max_size=10, min_idle=2.

SSL/TLS

For Required and LoginOnly encryption, you must specify how to validate the server certificate:

Option 1: Trust Server Certificate (development/self-signed certs):

from fastmssql import SslConfig, EncryptionLevel, Connection

ssl = SslConfig(
    encryption_level=EncryptionLevel.Required,
    trust_server_certificate=True
)

async with Connection(conn_str, ssl_config=ssl) as conn:
    ...

Option 2: Custom CA Certificate (production):

from fastmssql import SslConfig, EncryptionLevel, Connection

ssl = SslConfig(
    encryption_level=EncryptionLevel.Required,
    ca_certificate_path="/path/to/ca-cert.pem"
)

async with Connection(conn_str, ssl_config=ssl) as conn:
    ...

Note: trust_server_certificate and ca_certificate_path are mutually exclusive.

Helpers:

  • SslConfig.development() – encrypt, trust all (dev only)
  • SslConfig.with_ca_certificate(path) – use custom CA
  • SslConfig.login_only() / SslConfig.disabled() – legacy modes
  • SslConfig.disabled() – no encryption (not recommended)

Performance tips

For maximum throughput in highly concurrent scenarios, use multiple Connection instances (each with its own pool) and batch your work:

import asyncio
from fastmssql import Connection, PoolConfig

async def worker(conn_str, cfg):
    async with Connection(conn_str, pool_config=cfg) as conn:
        for _ in range(1000):
            _ = (await conn.query("SELECT 1 as v")).rows()

async def main():
    conn_str = "Server=.;Database=master;User Id=sa;Password=StrongPwd;"
    cfg = PoolConfig.high_throughput()
    await asyncio.gather(*[asyncio.create_task(worker(conn_str, cfg)) for _ in range(32)])

asyncio.run(main())

Examples & benchmarks

  • Examples: examples/comprehensive_example.py
  • Benchmarks: benchmarks/

Troubleshooting

  • Import/build: ensure Rust toolchain and maturin are installed if building from source
  • Connection: verify connection string; Windows auth not supported
  • Timeouts: increase pool size or tune connection_timeout_secs
  • Parameters: use @P1, @P2, ... and pass a list of values

Contributing

Contributions are welcome. Please open an issue or PR.

License

FastMSSQL is licensed under MIT:

See the LICENSE file for details.

Third‑party attributions

Built on excellent open source projects: Tiberius, PyO3, pyo3‑asyncio, bb8, tokio, serde, pytest, maturin, and more. See licenses/NOTICE.txt for the full list. The full texts of Apache‑2.0 and MIT are in licenses/.

Acknowledgments

Thanks to the maintainers of Tiberius, PyO3, pyo3‑asyncio, Tokio, pytest, maturin, and the broader open source community.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastmssql-0.5.2.tar.gz (184.5 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

fastmssql-0.5.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.3 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ x86-64

fastmssql-0.5.2-cp314-cp314t-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.14tWindows x86-64

fastmssql-0.5.2-cp314-cp314t-macosx_10_15_universal2.whl (2.4 MB view details)

Uploaded CPython 3.14tmacOS 10.15+ universal2 (ARM64, x86-64)

fastmssql-0.5.2-cp310-abi3-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.10+Windows x86-64

fastmssql-0.5.2-cp310-abi3-musllinux_1_1_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.10+musllinux: musl 1.1+ x86-64

fastmssql-0.5.2-cp310-abi3-musllinux_1_1_aarch64.whl (1.2 MB view details)

Uploaded CPython 3.10+musllinux: musl 1.1+ ARM64

fastmssql-0.5.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ x86-64

fastmssql-0.5.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ ARM64

fastmssql-0.5.2-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (2.4 MB view details)

Uploaded CPython 3.10+macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

File details

Details for the file fastmssql-0.5.2.tar.gz.

File metadata

  • Download URL: fastmssql-0.5.2.tar.gz
  • Upload date:
  • Size: 184.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for fastmssql-0.5.2.tar.gz
Algorithm Hash digest
SHA256 53b2441080f3865f3cfd8f927d7cfbe655bde03a7a5d70614560d833d554adb1
MD5 a63e5b0c87fc9ad9ecea948c5c5ed219
BLAKE2b-256 c3d8d6ff34741ed7779fcc25dee9b16515d74aac7aa873638f0b790d05d6c362

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmssql-0.5.2.tar.gz:

Publisher: build-wheels.yml on Rivendael/FastMssql

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastmssql-0.5.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for fastmssql-0.5.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 4e192be2401f4ef3bae6712439708f8ee9f21e0ae6f49243c3740e2aa660ef11
MD5 41ff79de3f9989dde595e13a7505c865
BLAKE2b-256 4814785f2ac6dec6f9d1f5c063508e5b313724e399206b9dba7f9e250b8bf084

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmssql-0.5.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: build-wheels.yml on Rivendael/FastMssql

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastmssql-0.5.2-cp314-cp314t-win_amd64.whl.

File metadata

  • Download URL: fastmssql-0.5.2-cp314-cp314t-win_amd64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.14t, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fastmssql-0.5.2-cp314-cp314t-win_amd64.whl
Algorithm Hash digest
SHA256 8a0aac6d1601fbe6194ecb959ae657c8707b8014bca4d8a4b85b3908223fd187
MD5 176803b56e04575ce7ad374b742afde6
BLAKE2b-256 d168fd3cc07d060876274054a67ef97d2cbb6ffa00a305a642cf1d734ea269f8

See more details on using hashes here.

File details

Details for the file fastmssql-0.5.2-cp314-cp314t-macosx_10_15_universal2.whl.

File metadata

  • Download URL: fastmssql-0.5.2-cp314-cp314t-macosx_10_15_universal2.whl
  • Upload date:
  • Size: 2.4 MB
  • Tags: CPython 3.14t, macOS 10.15+ universal2 (ARM64, x86-64)
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for fastmssql-0.5.2-cp314-cp314t-macosx_10_15_universal2.whl
Algorithm Hash digest
SHA256 f32a65e56a52be2c0078261c727ee4ac36c4c2c4c0386b6ac9ba77cc8076a149
MD5 f5ee577dbbb0001a783a62a19cfe40f5
BLAKE2b-256 341cef16d308b74b0dc22fc33b71e32384ecd13c3244719b8894969675687bd5

See more details on using hashes here.

File details

Details for the file fastmssql-0.5.2-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: fastmssql-0.5.2-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for fastmssql-0.5.2-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 9aa1dcd71e7af3b97389d8eb3886f5f1f46b250df2e6bb6045e3089360716d5d
MD5 5a767a3752a59f880f792e1cf833f313
BLAKE2b-256 8ab5597101dcb31d3e35b2f4e6082b0f32fad30ba0452f7c9eb92fe5b23c7f8f

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmssql-0.5.2-cp310-abi3-win_amd64.whl:

Publisher: build-wheels.yml on Rivendael/FastMssql

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastmssql-0.5.2-cp310-abi3-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for fastmssql-0.5.2-cp310-abi3-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 77acfb1c158a568e0ec05c71291948b991cf19dd81403103cfb28bdd9c8a5991
MD5 9514cd1862df3115845116f1b96edd0d
BLAKE2b-256 e1ff6e8a8c644e64a7e2d5ba798f26726824a3c668ce7efd250448013f5861b7

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmssql-0.5.2-cp310-abi3-musllinux_1_1_x86_64.whl:

Publisher: build-wheels.yml on Rivendael/FastMssql

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastmssql-0.5.2-cp310-abi3-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for fastmssql-0.5.2-cp310-abi3-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 ea076ea01b41f6ef6cfc871f5b71fbea6d6a7865751f86ba5d5de8ce2a45eefa
MD5 bd0614713158ed9c5ed09b57a12bbb8c
BLAKE2b-256 5c5bed96c70d45a417b132f272fcb96a550bda97b0eda0335c3be81f2c875d7c

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmssql-0.5.2-cp310-abi3-musllinux_1_1_aarch64.whl:

Publisher: build-wheels.yml on Rivendael/FastMssql

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastmssql-0.5.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for fastmssql-0.5.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0bd88ce168c530a11a337f80189c6d1a98a69074f076d84dffd5b144f231d917
MD5 6064130d1d03e17588b7aa30c6831fb5
BLAKE2b-256 ed770ac1d865fa4a765eee46fee166e52c1dc078dc874f65c0aa1336ceafae11

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmssql-0.5.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: build-wheels.yml on Rivendael/FastMssql

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastmssql-0.5.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for fastmssql-0.5.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 f112a49febf635db3a53a10bc63659646b14cc9476c5c6945b93ae0cbfb82275
MD5 b591c5e0aeccf0f4caaae470e5dc92b3
BLAKE2b-256 74835346461743bc480030e39ecbe850d079f4c914cae2f1e8e0fccd2fca7c2f

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmssql-0.5.2-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: build-wheels.yml on Rivendael/FastMssql

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastmssql-0.5.2-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for fastmssql-0.5.2-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 1d99636df1975c721c4992ddef2c9327e5bb94e026146272c4559415316d2afb
MD5 b963f6bf4c138a4279417685c512d4b7
BLAKE2b-256 2239e5444c904a1e1edb82c21b1849faa6c10f82768f178e0ea3371e1b1b79a8

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmssql-0.5.2-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:

Publisher: build-wheels.yml on Rivendael/FastMssql

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page