---
title: "Python sync API"
description: "Use the synchronous Python Developer SDK API for scripts, CLIs, and non-async applications. Connect, create, read, and update Aerospike records with blocking calls."
---

# Python sync API

> For the complete documentation index see: [llms.txt](https://aerospike.com/docs/llms.txt)
> 
> All documentation pages available in markdown.

The Aerospike [Python SDK](https://aerospike-python-sdk.readthedocs.io/en/latest/index.html) provides a synchronous API for applications that do not use `asyncio`. Use [`SyncClient`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/client.html) for scripts, CLIs, batch jobs, and other blocking code paths. The fluent builder surface matches the async API: chain methods on a session, then call `.execute()`.

## Applies to

-   Aerospike Developer SDK preview (Python 3.10+)
-   Package: `aerospike-sdk`
-   Aerospike Database 6.0 or later unless a section states otherwise

## Prerequisites

The Python SDK supports Python 3.10 and later. For best performance, use Python 3.14 or later to take advantage of free-threading and other runtime improvements in the 3.14 series. See the [Python 3.14 release notes](https://www.python.org/downloads/release/python-3140/) for details.

-   The Developer SDK [installed](https://aerospike.com/docs/develop/client/sdk/install)
-   A running Aerospike cluster reachable from your host (see [Connect to Aerospike](https://aerospike.com/docs/develop/client/sdk/connect))

## Async vs sync

| API | Entry point | Best for |
| --- | --- | --- |
| **Async** | [`Client`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/client.html) | Web servers, workers, and other `asyncio` applications |
| **Sync** | [`SyncClient`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/client.html) | Scripts, CLIs, and code without an event loop |

The synchronous API mirrors the async surface. Drop `async`/`await`, use a regular `with` statement for the client, and iterate query results with a standard `for` loop instead of `async for`. Shared types such as [`DataSet`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/dataset.html) and [`Behavior`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/behavior.html) work the same in both APIs.

## Key concepts

| Concept | Role |
| --- | --- |
| [`SyncClient`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/client.html) | Connects to the cluster and manages the connection lifecycle |
| [`SyncSession`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/session.html) | Executes reads and writes using a chosen behavior (timeouts, retries, consistency) |
| [`DataSet`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/dataset.html) | Namespace and set pair; use `.id(key)` to build record keys |
| [`SyncQueryBuilder`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/query.html) | Configures reads; call `.execute()` to get a [`RecordStream`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/record-stream.html) |
| [`SyncWriteSegmentBuilder`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/write-segment.html) | Configures writes; chain bin operations, then call `.execute()` |

## Connect and create a session

Open a client with a context manager so the connection closes automatically:

```python
from aerospike_sdk import Behavior, DataSet, SyncClient

with SyncClient("localhost:3000") as client:

    session = client.create_session(Behavior.DEFAULT)

    users = DataSet.of("test", "users")

    # Use session for reads and writes...
```

> 📖 **API reference**: [`SyncClient`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/client.html#aerospike%5Fsdk.sync.client.SyncClient) | [`SyncClient.create_session()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/client.html#aerospike%5Fsdk.sync.client.SyncClient.create%5Fsession) | [`Behavior.DEFAULT`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/behavior.html#aerospike%5Fsdk.policy.behavior.Behavior.DEFAULT) | [`DataSet.of()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/dataset.html#aerospike%5Fsdk.dataset.DataSet.of)

For TLS, authentication, and advanced cluster configuration, see [Connect to Aerospike](https://aerospike.com/docs/develop/client/sdk/connect) and the Python SDK [connecting guide](https://aerospike-python-sdk.readthedocs.io/en/latest/guide/connecting.html).

## Create records

Write operations start on [`SyncSession`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/session.html) and return a [`SyncWriteSegmentBuilder`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/write-segment.html). Chain bin methods, then call `.execute()`.

### Upsert (create or update)

Use `upsert()` when the record may or may not already exist:

```python
with SyncClient("localhost:3000") as client:

    session = client.create_session(Behavior.DEFAULT)

    users = DataSet.of("test", "users")

    session.upsert(users.id("user-1")).bin("name").set_to("Alice").bin("age").set_to(30).execute()
```

You can also set multiple bins at once with `.put()`:

```python
session.upsert(users.id("user-1")).put(

    {"name": "Alice", "email": "alice@example.com", "status": "active", "age": 30}

).execute()
```

### Insert (create only)

Use `insert()` when the record must not already exist. The call fails if the key is taken:

```python
session.insert(users.id("user-2")).put({"name": "Bob", "age": 25}).execute()
```

> 📖 **API reference**: [`SyncSession.upsert()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/session.html#aerospike%5Fsdk.sync.session.SyncSession.upsert) | [`SyncSession.insert()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/session.html#aerospike%5Fsdk.sync.session.SyncSession.insert) | [`SyncWriteSegmentBuilder.set_to()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/write-segment.html#aerospike%5Fsdk.sync.operations.query.SyncWriteSegmentBuilder.set%5Fto) | [`SyncWriteSegmentBuilder.put()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/write-segment.html#aerospike%5Fsdk.sync.operations.query.SyncWriteSegmentBuilder.put) | [`SyncWriteSegmentBuilder.execute()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/write-segment.html#aerospike%5Fsdk.sync.operations.query.SyncWriteSegmentBuilder.execute)

See [Create records](https://aerospike.com/docs/develop/client/sdk/usage/create) for TTL, batch creation, and collection data types.

## Read records

Reads go through `session.query()`, which returns a [`SyncQueryBuilder`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/query.html). Call `.execute()` to get a stream of [`RecordResult`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/record-result.html) objects.

### Point read (single key)

```python
with SyncClient("localhost:3000") as client:

    session = client.create_session(Behavior.DEFAULT)

    users = DataSet.of("test", "users")

    stream = session.query(users.id("user-1")).execute()

    result = stream.first_or_raise()

    print(result.record.bins)  # {'name': 'Alice', 'age': 30, ...}

    stream.close()
```

### Query with an AEL filter

Filter records server-side with [Aerospike Expression Language (AEL)](https://aerospike.com/docs/develop/client/sdk/concepts/ael):

```python
stream = session.query(users).where("$.status == 'active' and $.age > 21").execute()

for result in stream:

    print(result.record.bins)

stream.close()
```

Return only specific bins to reduce network transfer:

```python
stream = session.query(users.id("user-1")).bins(["name", "email"]).execute()

result = stream.first_or_raise()

print(result.record.bins)

stream.close()
```

> 📖 **API reference**: [`SyncSession.query()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/session.html#aerospike%5Fsdk.sync.session.SyncSession.query) | [`SyncQueryBuilder.where()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/query.html#aerospike%5Fsdk.sync.operations.query.SyncQueryBuilder.where) | [`SyncQueryBuilder.bins()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/query.html#aerospike%5Fsdk.sync.operations.query.SyncQueryBuilder.bins) | [`SyncQueryBuilder.execute()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/query.html#aerospike%5Fsdk.sync.operations.query.SyncQueryBuilder.execute) | [`RecordStream.first_or_raise()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/record-stream.html#aerospike%5Fsdk.record%5Fstream.RecordStream.first%5For%5Fraise)

See [Read records](https://aerospike.com/docs/develop/client/sdk/usage/read) and [Query by field values](https://aerospike.com/docs/develop/client/sdk/usage/query) for batch reads, partition filters, and query policies.

## Modify records

Use `update()` when the record must already exist. Chain bin operations on [`SyncWriteSegmentBuilder`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/write-segment.html), then call `.execute()`.

1.  Update a bin value.
    
    ```python
    with SyncClient("localhost:3000") as client:
    
        session = client.create_session(Behavior.DEFAULT)
    
        users = DataSet.of("test", "users")
    
        session.update(users.id("user-1")).bin("email").set_to("alice.smith@example.com").execute()
    ```
    
2.  Increment a numeric bin.
    
    ```python
    session.update(users.id("user-1")).bin("login_count").increment_by(1).execute()
    ```
    
3.  Apply a server-side filter so only matching records are updated.
    
    ```python
    session.update(users.id("user-1")).where("$.age >= 18").bin("verified").set_to(True).execute()
    ```
    
4.  Replace all bins.
    
    `replace()` writes the bins you specify. The record is created if it does not already exist; existing bins not in the write are removed.
    
    ```python
    session.replace(users.id("user-1")).put({"name": "Alice Updated"}).execute()
    ```
    
    Use [`replace_if_exists()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/session.html#aerospike%5Fsdk.sync.session.SyncSession.replace_if_exists) if you require the record to already exist.
    

> 📖 **API reference**: [`SyncSession.update()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/session.html#aerospike%5Fsdk.sync.session.SyncSession.update) | [`SyncSession.replace()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/session.html#aerospike%5Fsdk.sync.session.SyncSession.replace) | [`SyncWriteSegmentBuilder.increment_by()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/write-segment.html#aerospike%5Fsdk.sync.operations.query.SyncWriteSegmentBuilder.increment%5Fby) | [`SyncWriteSegmentBuilder.where()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/sync/write-segment.html#aerospike%5Fsdk.sync.operations.query.SyncWriteSegmentBuilder.where)

See [Update records](https://aerospike.com/docs/develop/client/sdk/usage/update) and the Python SDK [writing guide](https://aerospike-python-sdk.readthedocs.io/en/latest/guide/writes.html) for conditional writes, generation checks, TTL, and batch updates.

## Delete records

Remove a single key:

```python
session.delete(users.id("user-1")).execute()
```

See [Delete records](https://aerospike.com/docs/develop/client/sdk/usage/delete) for durable delete and batch deletion patterns.

## Complete example

The script below connects to a local cluster, creates two records, reads them back, updates one record, and cleans up. Save it as `sync_example.py` and run it against a cluster on `localhost:3000`:

Terminal window

```bash
python sync_example.py
```

```python
from aerospike_sdk import Behavior, DataSet, SyncClient

def main() -> None:

    with SyncClient("localhost:3000") as client:

        session = client.create_session(Behavior.DEFAULT)

        users = DataSet.of("test", "users")

        # Cleanup from prior runs so the script is repeatable.

        for user_id in ("user-1", "user-2"):

            session.delete(users.id(user_id)).execute()

        # Create: upsert the first user.

        session.upsert(users.id("user-1")).put(

            {

                "name": "Alice",

                "email": "alice@example.com",

                "status": "active",

                "age": 30,

                "login_count": 0,

            }

        ).execute()

        # Create: insert a second user (fails if the key already exists).

        session.insert(users.id("user-2")).put(

            {"name": "Bob", "age": 25, "status": "active"}

        ).execute()

        # Read: point read by key.

        stream = session.query(users.id("user-1")).execute()

        user = stream.first_or_raise().record

        print(f"User 1: {user.bins}")

        stream.close()

        # Read: query active users over 21 with AEL.

        stream = session.query(users).where("$.status == 'active' and $.age > 21").execute()

        print("Active users over 21:")

        for result in stream:

            print(f"  - {result.record.bins.get('name')}")

        stream.close()

        # Modify: update email, increment a counter, and set a conditional flag.

        session.update(users.id("user-1")).bin("email").set_to("alice.smith@example.com").execute()

        session.update(users.id("user-1")).bin("login_count").increment_by(1).execute()

        session.update(users.id("user-1")).where("$.age >= 18").bin("verified").set_to(True).execute()

        # Read back selected bins.

        stream = session.query(users.id("user-1")).bins(["name", "email", "login_count", "verified"]).execute()

        updated = stream.first_or_raise().record

        print(f"Updated user 1: {updated.bins}")

        stream.close()

        # Cleanup.

        session.delete(users.id("user-1")).execute()

        session.delete(users.id("user-2")).execute()

        print("Done.")

if __name__ == "__main__":

    main()
```

Expected output (bin order may vary):

```plaintext
User 1: {'name': 'Alice', 'email': 'alice@example.com', 'status': 'active', 'age': 30, 'login_count': 0}

Active users over 21:

  - Alice

Updated user 1: {'name': 'Alice', 'email': 'alice.smith@example.com', 'login_count': 1, 'verified': True}

Done.
```

## Next steps

Quickstart

Run a complete end-to-end example in under 5 minutes.

[Quickstart →](https://aerospike.com/docs/develop/client/sdk/quickstart)

Python SDK docs

Full guides and sync API reference on Read the Docs.

[Python SDK →](https://aerospike-python-sdk.readthedocs.io/en/latest/index.html)

-   [Connect to Aerospike](https://aerospike.com/docs/develop/client/sdk/connect)
-   [Use transactions](https://aerospike.com/docs/develop/client/sdk/usage/transactions)
-   [Handle errors gracefully](https://aerospike.com/docs/develop/client/sdk/concepts/errors)