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:

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

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

from fastmssql import SslConfig, EncryptionLevel, Connection

ssl = SslConfig(
    encryption_level=EncryptionLevel.REQUIRED,  # or "Required"
    trust_server_certificate=False,
)

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

Helpers:

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

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

Uploaded CPython 3.10+Windows x86-64

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

Uploaded CPython 3.10+musllinux: musl 1.1+ ARM64

fastmssql-0.4.8-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.4.8-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.4.8-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.4.8.tar.gz.

File metadata

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

File hashes

Hashes for fastmssql-0.4.8.tar.gz
Algorithm Hash digest
SHA256 22c2e46868fcb5230be44a1bec790a6e326edcd5e53cfe400e8fd1bf909602d0
MD5 b24e4009316cebc7b0b6c36c9abab6c2
BLAKE2b-256 8fbd938214d7e07c1541ca24fef8cfe9c53b747a948c5ced967ba397442e57c6

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for fastmssql-0.4.8-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 52f7b67ceebb86b35bc9a8e7103ef0fd22727cb150cec04564f303f9435ac041
MD5 4c5ff29b17a34d25002c035144a840e9
BLAKE2b-256 cf205c04c190fad8339e171f94a8e21fb8a7bca1a6b8268a83472d3739711aee

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: fastmssql-0.4.8-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.4.8-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 56a7e2bcd5083f38776229fe531e8c9a71c35d55f58cd9e7509b8347173c5997
MD5 e59156047548eea7aad26e66f5b4230e
BLAKE2b-256 b053d74a7f2b9e905c3ba479b4dd8f6acf801d401fc2921d1e3a1b8eec8e6aeb

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for fastmssql-0.4.8-cp310-abi3-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 1c3f5746b555e308c2d5916a582b14ecf267b82aba39cca97158fd23de6fb805
MD5 b67fbb3717a440cd888686e90feb29ac
BLAKE2b-256 38d0027808e5f67ea460e75f591a18f45abcc57bca62db02e6e4b3b687b007e2

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for fastmssql-0.4.8-cp310-abi3-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 958ab2b3826e46759b73fe38dab1833b7df86627471f2825f346150b3d7d0ea4
MD5 b88ba37f584b73a8c0a8777d4afce6a3
BLAKE2b-256 b70266ddffeff3522445ed8d8afae0626892bae7c0c3b05b0a0e11bb7a6efddf

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for fastmssql-0.4.8-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0ebe2475129ddbea82c686e66f97f1f77391296fc0e2025d87b2149ef990df7b
MD5 b47fee0f5a4f0695a5a7f4e6e81b33ee
BLAKE2b-256 b457044a05fdd150a8cc33374e86d9a84c99b4074645d9e53f28f1abaf333a5f

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for fastmssql-0.4.8-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 2c4d730335605423868a50f9d85cd5c72ea35a08e7679ce9c5eefa4ab901221e
MD5 e1e21f3ef00327e4aeedae012c9f2d34
BLAKE2b-256 414c955506844c83fc7449b9dde01656bbcad7183ed6883caedb660c9b81def2

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastmssql-0.4.8-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.4.8-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for fastmssql-0.4.8-cp310-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 2779cf7cad7fbe241eb8f4a788a9836a3997c921956c65d011352544a350cc76
MD5 643b6715d9fa508b11b7aedaea576530
BLAKE2b-256 0ef46f54efd4db9fd2198a982f8dcc342aad427e210c3ac057c03a62d0f877e0

See more details on using hashes here.

Provenance

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