Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

Aerospike Python SDK

A modern, developer-friendly interface for Aerospike. Async-first, Pythonic API with a chainable session model, fluent query builder, and AEL string filters over the Aerospike Python Async Client.

Status: Public preview (alpha). Not yet production-ready; feedback welcome via GitHub Issues.

Resources

Installation

pip install aerospike-sdk

Pin to a specific release if you need reproducible builds:

pip install aerospike-sdk==0.9.0a2

This installs the SDK plus its dependency on the Aerospike Python Async Client (aerospike-async). No Rust toolchain or git checkout required for ordinary use — pre-built wheels are available for Linux, macOS, and Windows on Python 3.10–3.14.

Quick start

import asyncio
from aerospike_sdk import Behavior, Client, DataSet


async def main():
    async with Client("localhost:3000") as client:
        session = client.create_session(Behavior.DEFAULT)
        users = DataSet.of("test", "users")

        # High-level key-value writes
        await session.upsert(users.id(1)).put({"name": "Alice", "age": 28, "country": "UK"}).execute()
        await session.upsert(users.id(2)).put({"name": "Bob", "age": 35, "country": "US"}).execute()

        # Filtered query with AEL — streams results memory-efficiently
        results = await (
            session.query(users)
            .where("$.age > 25 and $.country == 'US'")
            .execute()
        )
        async for row in results:
            if row.is_ok and row.record is not None:
                print(row.record.bins)

        # Or drain the entire stream into a list
        all_users = await session.query(users).execute()
        rows = await all_users.collect()


asyncio.run(main())

Sync

The same surface is available without asyncio via SyncClient. No async/await, no event loop — useful for sync codebases or when a dependency forbids asyncio.

from aerospike_sdk import Behavior, DataSet, SyncClient


def main():
    with SyncClient("localhost:3000") as client:
        session = client.create_session(Behavior.DEFAULT)
        users = DataSet.of("test", "users")

        # High-level key-value writes
        session.upsert(users.id(1)).put({"name": "Alice", "age": 28, "country": "UK"}).execute()
        session.upsert(users.id(2)).put({"name": "Bob", "age": 35, "country": "US"}).execute()

        # Filtered query with AEL — same builder API as async
        results = (
            session.query(users)
            .where("$.age > 25 and $.country == 'US'")
            .execute()
        )
        for row in results:
            if row.is_ok and row.record is not None:
                print(row.record.bins)


main()

SyncClient is a thin façade over the PAC _blocking surface — there is no per-call event loop and no per-thread loop runner. Sessions, behaviors, builders, and AEL filters are identical to the async path.

See the Quick Start guide for a deeper walkthrough; the API reference covers every public class and method in detail.

Performance modes

PSDK offers two API shapes — pick based on what your code needs.

API Use when Trade-off
Chained builder (session.query(k).execute(), session.upsert(k).put(...).execute()) You need filters (where(...)), batch ops, error handlers, secondary-index queries, TTL overrides, generation checks, etc. Same shape as the Aerospike Java SDK. Builder + stream wrapping costs ~60 µs/op of Python overhead.
Fast-path (session.get(key), session.put(key, bins)) Single-key reads/writes where you want the lowest per-op overhead. Single-key only; no filters, no error-handler callbacks, no batch semantics. Errors raise directly.

Both shapes work in sync and async modes. Use whichever fits each call site — they share the same Session and Behavior.

Free-threaded Python

For high-throughput multi-threaded workloads, run PSDK on the free-threaded build with the GIL disabled:

# uv example — install once, then always launch with PYTHON_GIL=0
uv python install 3.14.5+freethreaded
PYTHON_GIL=0 python my_app.py

Verify with sys._is_gil_enabled() == False after imports — if any non-FT-safe C extension is imported, the interpreter silently re-enables the GIL and your multi-threaded perf collapses 4-6×.

AsyncPool (multi-loop async) is a free-threading feature — don't use it on regular Python, it's slower than a single-client setup there. Each pool spawns N event loops on N OS threads, each with its own Client; coroutines submitted via pool.run(...) round-robin across loops:

from aerospike_sdk import AsyncPool, Behavior, Client, DataSet


async def main():
    pool = AsyncPool(
        client_factory=lambda: Client("localhost:3000"),
        loop_count=4,
    )
    async with pool:
        users = DataSet.of("test", "users")

        # Submit a coroutine — picks an idle loop round-robin
        await pool.run(
            lambda client: client.create_session(Behavior.DEFAULT)
                                 .upsert(users.id(1))
                                 .put({"name": "Alice"})
                                 .execute()
        )

Tune loop_count based on your workload — os.cpu_count() is the default. Cluster-wide index metadata is shared via a single IndexesMonitor across the pool, so sindex-list load doesn't scale with loop_count.

For the full decision guide, the trade-offs, and measured TPS/latency across all modes, see docs/guide/performance.md. For the raw bench data and methodology, see docs/guide/benchmarking.md.

Documentation

The two complement each other: the guide site introduces concepts and works through realistic examples, while the API reference is the exhaustive source for Client, Session, query/update builders, AEL, behavior policies, and every public symbol.

Versioning

PSDK follows SemVer. Pre-releases use the MAJOR.MINOR.PATCH-{alpha,beta,rc}.N form (e.g. 0.9.0-alpha.1). PyPI normalizes these on upload to the equivalent PEP 440 spelling (0.9.0a1).

The top-level VERSION file is the single source of truth; pyproject.toml reads it dynamically, so the wheel and the working tree are guaranteed to match. See the Development section below for the bump procedure.

License

Apache License 2.0. See LICENSE for details.


Development / Contributing

The sections below are for SDK contributors. Downstream users do not need any of this — pip install aerospike-sdk is sufficient to use the package.

Prerequisites

  • Python 3.10 - 3.14, or 3.14t (free-threaded) for high-throughput / AsyncPool work. Recommended installer: uv (uv python install 3.14.5+freethreaded) or pyenv with a dedicated environment. Free-threaded wheels (cp313t / cp314t) ship across the same platform matrix as the regular CPython wheels starting with aerospike-async v0.5.0-alpha.1.
  • Aerospike server — required for integration tests
  • Rust toolchain (rustc + cargo) — required only when building the Aerospike Python Async Client from source (e.g. for an unreleased PAC feature)
  • Java 11+ — required for the one-time AEL parser build (make generate-ael)

Setting up a dev environment

make generate-ael          # one-time: build the ANTLR AEL parser (requires Java 11+)
pip install -e ".[dev]"    # install with dev extras

make generate-ael only needs to be re-run if aerospike_sdk/ael/antlr4/Condition.g4 changes.

Local PAC checkout

To test against a sibling Aerospike Python Async Client working tree (e.g. for a feature not yet on PyPI), install it editable first and pass --no-deps to this SDK so pip doesn't try to re-resolve PAC from PyPI:

pip install -e /path/to/aerospike-client-python-async
pip install -e ".[dev]" --no-deps

Or use requirements-local.txt (gitignored path example).

Configuration

Copy aerospike.env.example to aerospike.env in the repo root and adjust hosts or ports. aerospike.env is not committed.

cp aerospike.env.example aerospike.env
source aerospike.env

Pytest loads aerospike.env when present; otherwise conftest.py loads aerospike.env.example for unset variables only (so CI env vars still win).

Running tests

make test          # all tests
make test-unit     # unit tests only
make test-int      # integration tests only (requires running Aerospike server)

macOS file descriptor limit. On macOS, you may encounter OSError: [Errno 24] Too many open files when running the full test suite. The default limit (256) is not enough for the concurrent async connections created during testing.

ulimit -n 4096

To make this permanent, add it to your shell profile (~/.zshrc or ~/.bash_profile).

Building docs locally

API docs are built with Sphinx (Furo theme, MyST-Parser for Markdown). The same Sphinx config is what Read the Docs builds from.

pip install -e ".[docs]"   # one-time: install Sphinx toolchain
make docs                  # build static HTML to docs/_build/html/
make docs-serve            # live-reloading local preview

Docstrings use Google style with Sphinx cross-references (:meth:, :class:, etc.).

Lint

ruff check .

Bumping the version

Bumps are manual and happen in PRs against dev. Promotion workflows (dev → stage → main) do not mutate the version.

# 1. Edit VERSION:
#    e.g. 0.9.0-alpha.1  →  0.9.0-alpha.2
echo '0.9.0-alpha.2' > VERSION

# 2. Confirm:
bin/get-version    # prints 0.9.0-alpha.2

# 3. Open a PR against dev with just this change.

Bumping the PAC pin

PSDK depends on a published release of the Aerospike Python Async Client on PyPI as aerospike-async. On dev and downstream release branches the pin must be a published PyPI version. The pin lives in pyproject.toml under [project] dependencies:

[project]
dependencies = [
    "aerospike-async==0.5.0a1",
    # ...other deps
]

To bump: change the version to the new release on PyPI, then reinstall:

pip install --upgrade "aerospike-async==0.5.0aN"

Open the PR against dev. PSDK's own VERSION does not need to change for a PAC pin bump unless the underlying API contract has shifted enough to warrant it.

Mid-cycle: pinning a tagged but unpublished PAC

During a breaking-change cycle, the new PAC may be git-tagged on GitHub before its PyPI wheel is published. Feature branches (not dev) may temporarily pin to the git ref to validate against the new PAC before publish:

[project]
dependencies = [
    #"aerospike-async==0.5.0a1",   # ← restore this form before merging to dev
    "aerospike-async @ git+ssh://git@github.com/aerospike/aerospike-client-python-async.git@v0.5.0-alpha.1",
    # ...other deps
]

Use git refs only on feature branches; switch back to the ==X.Y.ZaN form before opening a PR against dev. CI reads the PAC ref out of pyproject.toml at job start, so both forms work transparently for the build matrix.

Reading the version programmatically

Anywhere a build script, CI step, or release tool needs the version:

bin/get-version    # → 0.9.0-alpha.1

The script reads VERSION and trims trailing whitespace. No Python or setuptools runtime dependency — usable from any shell, container, or CI environment.

Metadata

Release files for aerospike-sdk 0.9.0a5

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

Source distribution (sdist)

Source distribution for aerospike-sdk 0.9.0a5
File Size Uploaded
aerospike_sdk-0.9.0a5.tar.gz 264.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for aerospike-sdk 0.9.0a5
File Interpreter ABI Platform
aerospike_sdk-0.9.0a5-py3-none-any.whl Python 3 none any Details

Total release size: 573.8 kB

Release files / aerospike_sdk-0.9.0a5.tar.gz

Download URL aerospike_sdk-0.9.0a5.tar.gz
Size 264.2 kB
Tags Source
SHA-256 checksum
How to use checksums
275a8f3df3761b87676a02409e314a87f7218a0bb7f1ac28fd373b4d3d3a3486
BLAKE2b-256 checksum
How to use checksums
932f2a04731ff95ea114c3148218ac43febb9f28361e7e21bf77d5e7464e9d77
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Jun 17, 2026.

Transparency log

Release files / aerospike_sdk-0.9.0a5-py3-none-any.whl

Download URL aerospike_sdk-0.9.0a5-py3-none-any.whl
Size 309.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6ac1cfcae00c5e49117d081559f39855d4d1859fbb94e5fbb1769ead0e4acd19
BLAKE2b-256 checksum
How to use checksums
e1e1a3e7671fc455fab91dfefe1eba3bf3f236d1174cdc704df61cbaa1021174
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Jun 17, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.9.0a5 This release

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