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
- PyPI: https://pypi.org/project/aerospike-sdk/
- Documentation: https://aerospike.com/docs/develop/client/sdk/
- API Reference: https://aerospike-python-sdk.readthedocs.io/
- Source: https://github.com/aerospike/aerospike-client-python-sdk
- Issues: https://github.com/aerospike/aerospike-client-python-sdk/issues
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
- Guides and tutorials (user-facing, hand-curated): https://aerospike.com/docs/develop/client/sdk/
- API reference (auto-generated from docstrings, hosted on Read the Docs): https://aerospike-python-sdk.readthedocs.io/
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 /
AsyncPoolwork. Recommended installer:uv(uv python install 3.14.5+freethreaded) orpyenvwith a dedicated environment. Free-threaded wheels (cp313t/cp314t) ship across the same platform matrix as the regular CPython wheels starting withaerospike-asyncv0.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)
| File | Size | Uploaded | |
|---|---|---|---|
| aerospike_sdk-0.9.0a5.tar.gz | 264.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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