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.0.tar.gz (170.1 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.0-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.0-cp310-abi3-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.10+Windows x86-64

fastmssql-0.5.0-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.0-cp310-abi3-musllinux_1_1_aarch64.whl (1.2 MB view details)

Uploaded CPython 3.10+musllinux: musl 1.1+ ARM64

fastmssql-0.5.0-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.0-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.0-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (2.3 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.0.tar.gz.

File metadata

  • Download URL: fastmssql-0.5.0.tar.gz
  • Upload date:
  • Size: 170.1 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.0.tar.gz
Algorithm Hash digest
SHA256 a2f417df71d50cddcb9f04db8287f499ee5c584bb0f77d0736f38097df7fd743
MD5 ba7f2e9cd71540ec0727b38f1f087bf6
BLAKE2b-256 e76509aa5d591cefe44414095c9a5ae5298bb39212eba0473d9b36ccea833d69

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmssql-0.5.0.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.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for fastmssql-0.5.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 7edd0b90287e064f32997499586d6a9242283b892ec2f3bf10786b131615c23a
MD5 a9d611106c702d1735fdcb58a78faf81
BLAKE2b-256 f2ca3c2f604535a014e417401fe811e260d16b6e9798bd8225fa0fd5d5b4066c

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmssql-0.5.0-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.0-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: fastmssql-0.5.0-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.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 5314f73d27d442bc5729a12c6e2798a962f8e7db5059cd89d5e77441e9a20f46
MD5 1e7f05f36a4635a2ba5978d852b1f4dd
BLAKE2b-256 1a4fcf750dda7d56c5811ecb13074eff2878ad00e57e6d459c13ad061930c092

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmssql-0.5.0-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.0-cp310-abi3-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for fastmssql-0.5.0-cp310-abi3-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 abb46d9b5fb4aa43d9c7a90842a38c55d92c743337656422714999738ceecc46
MD5 237592970a3825e59cade4311b85b662
BLAKE2b-256 233f5889f285a539d06520e4cf3753d373326b4a6eca316c451c2b2fffe9dcb9

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmssql-0.5.0-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.0-cp310-abi3-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for fastmssql-0.5.0-cp310-abi3-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 08920f45b6a1107c606aa80b0e1298ec069f9c76c3847ac838dddbacf31b7e36
MD5 d57f813155e03333cb9b2df9ac26c6df
BLAKE2b-256 3c91292cf5d5c53a30fc30848d93ddd0441ab627dbaa57c783ef5326f05ca5dc

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmssql-0.5.0-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.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for fastmssql-0.5.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0e961c4c78da7f13f79e6675cf804d842c820fab8a740913c332ea7c26f7b949
MD5 5a0b1444e4eed1df91ec09d32af5da9b
BLAKE2b-256 6584ed4d932895e8f1c96ae414f0e3c5b556a4af915c30bbbd3fcd23d9367cb0

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmssql-0.5.0-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.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for fastmssql-0.5.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 1edf773a22a8d4703e1abe15ea7e6f913e60834f44812adc4de16f32c96ab4fe
MD5 dd3869e49400c9cc36b8e59578e562cc
BLAKE2b-256 df35da519622fd06ef1fc60e22ee478086f31b9cdb4e2bf9a2f9d8f0385a4c49

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmssql-0.5.0-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.0-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.0-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 c25778c6df17a45fa700d8c54fda976daae580ed158e068da530466a7ba42bf6
MD5 15d2f4739d4f2194b7c9bde70348427e
BLAKE2b-256 6cc7b794c4acc469a890cc5239c54428f325826b400747be9d0180967330e9bd

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmssql-0.5.0-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