---
title: "Understanding the fluent API"
description: "Learn the design philosophy of the Aerospike Developer SDK's fluent API and method chaining for Java and Python."
---

# Understanding the SDK API

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

This guide explains the design philosophy behind the Developer SDK and how to use its patterns effectively.

## Why fluent design?

The Developer SDK uses a **fluent interface** pattern—methods return the object itself, enabling method chaining that reads like natural language.

### Classic client vs. SDK client

-   [Java](#tab-panel-3006)
-   [Python](#tab-panel-3007)

```java
import java.time.Duration;

import com.aerospike.client.sdk.DataSet;

// Classic Client - verbose, configuration-heavy

WritePolicy policy = new WritePolicy();

policy.sendKey = true;

policy.expiration = 3600;

Key key = new Key("test", "users", "user-1");

Bin bin1 = new Bin("name", "Alice");

Bin bin2 = new Bin("age", 28);

client.put(policy, key, bin1, bin2);

// Developer SDK - chainable, readable

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

session.insert(users)

    .bins("name", "age")

    .id("user-1").values("Alice", 28)

    .sendKey()

    .expireRecordAfter(Duration.ofSeconds(3600))

    .execute();
```

> 📖 **API reference**: [`DataSet.of(...)`](https://javadoc.io/doc/com.aerospike/aerospike-client-sdk/latest/com/aerospike/client/sdk/DataSet.html#of%28java.lang.String%2Cjava.lang.String%29) | [`Key`](https://javadoc.io/doc/com.aerospike/aerospike-client-sdk/latest/com/aerospike/client/sdk/Key.html) | [`Session.insert(DataSet)`](https://javadoc.io/doc/com.aerospike/aerospike-client-sdk/latest/com/aerospike/client/sdk/Session.html#insert%28com.aerospike.client.sdk.DataSet%29) | [`OperationObjectBuilder.bins(...)`](https://javadoc.io/doc/com.aerospike/aerospike-client-sdk/latest/com/aerospike/client/sdk/OperationObjectBuilder.html#bins%28java.lang.String%2Cjava.lang.String...%29) | [`IdValuesBuilder.id(...)`](https://javadoc.io/doc/com.aerospike/aerospike-client-sdk/latest/com/aerospike/client/sdk/IdValuesBuilder.html#id%28java.lang.String%29) | [`IdValuesRowBuilder.values(...)`](https://javadoc.io/doc/com.aerospike/aerospike-client-sdk/latest/com/aerospike/client/sdk/IdValuesRowBuilder.html#values%28java.lang.Object...%29) | [`ChainableQueryBuilder.execute()`](https://javadoc.io/doc/com.aerospike/aerospike-client-sdk/latest/com/aerospike/client/sdk/ChainableQueryBuilder.html#execute%28%29)

```python
from aerospike_sdk import DataSet

# Classic Client - verbose, configuration-heavy

policy = {"key": aerospike.POLICY_KEY_SEND}

key = ("test", "users", "user-1")

bins = {"name": "Alice", "age": 28}

client.put(key, bins, policy=policy)

# Developer SDK - chainable, readable

# (`send_key` is a Behavior setting, not a builder method, and Behavior.DEFAULT

# already stores the original user key alongside the digest.)

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

await session.insert(key=users.id("user-1")).put(

    {"name": "Alice", "age": 28}

).expire_record_after_seconds(3600).execute()
```

> 📖 **API reference**: [`DataSet.of()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/dataset.html#aerospike%5Fsdk.dataset.DataSet.of) | [`DataSet.id()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/dataset.html#aerospike%5Fsdk.dataset.DataSet.id) | [`Behavior.DEFAULT`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/behavior.html#aerospike%5Fsdk.policy.behavior.Behavior.DEFAULT) | [`Session.insert()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/session.html#aerospike%5Fsdk.aio.session.Session.insert) | [`WriteSegmentBuilder.put()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/write-segment.html#aerospike%5Fsdk.aio.operations.query.WriteSegmentBuilder.put) | [`WriteSegmentBuilder.expire_record_after_seconds()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/write-segment.html#aerospike%5Fsdk.aio.operations.query.WriteSegmentBuilder.expire%5Frecord%5Fafter%5Fseconds) | [`WriteSegmentBuilder.execute()`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/write-segment.html#aerospike%5Fsdk.aio.operations.query.WriteSegmentBuilder.execute)

## Method chaining philosophy

Fluent interfaces follow these principles:

1.  **Discoverability**: IDE autocomplete guides you through available options
2.  **Readability**: Code reads like a sentence describing what it does
3.  **Immutability**: Each chain step returns a new builder (no mutation)
4.  **Terminal Operations**: Chains end with an action (`execute()`, then stream iteration for queries)

## Builder pattern integration

The Developer SDK uses builders for complex configuration:

-   [Java](#tab-panel-3008)
-   [Python](#tab-panel-3009)

```java
import com.aerospike.client.sdk.Cluster;

import com.aerospike.client.sdk.ClusterDefinition;

import com.aerospike.client.sdk.Host;

// Cluster connection (multiple seed hosts)

Cluster cluster = new ClusterDefinition(

    new Host("localhost", 3000),

    new Host("localhost", 3001)

).connect();

// Session from cluster

Session session = cluster.createSession(Behavior.DEFAULT);
```

> 📖 **API reference**: [`ClusterDefinition(Host...)`](https://javadoc.io/doc/com.aerospike/aerospike-client-sdk/latest/com/aerospike/client/sdk/ClusterDefinition.html#%3Cinit%3E%28com.aerospike.client.sdk.Host...%29) | [`Host(String,int)`](https://javadoc.io/doc/com.aerospike/aerospike-client-sdk/latest/com/aerospike/client/sdk/Host.html#%3Cinit%3E%28java.lang.String%2Cint%29) | [`Host(String,String,int)`](https://javadoc.io/doc/com.aerospike/aerospike-client-sdk/latest/com/aerospike/client/sdk/Host.html#%3Cinit%3E%28java.lang.String%2Cjava.lang.String%2Cint%29) | [`ClusterDefinition.connect()`](https://javadoc.io/doc/com.aerospike/aerospike-client-sdk/latest/com/aerospike/client/sdk/ClusterDefinition.html#connect%28%29) | [`Cluster.createSession(Behavior)`](https://javadoc.io/doc/com.aerospike/aerospike-client-sdk/latest/com/aerospike/client/sdk/Cluster.html#createSession%28com.aerospike.client.sdk.policy.Behavior%29)

```python
from aerospike_sdk import Behavior, ClusterDefinition, Host

# Cluster connection (async; multiple seed hosts)

cluster = await ClusterDefinition(

    hosts=[

        Host.of("localhost", 3000),

        Host.of("localhost", 3001),

    ]

).connect()

# Session from cluster

session = cluster.create_session(Behavior.DEFAULT)
```

> 📖 **API reference**: [`Behavior.DEFAULT`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/behavior.html#aerospike%5Fsdk.policy.behavior.Behavior.DEFAULT)

## When fluent shines

The fluent pattern is most valuable when:

-   Operations have many optional parameters
-   Configuration is complex but has sensible defaults
-   Code readability is important for maintenance
-   IDE support can guide developers

## Next steps

-   [Quickstart](https://aerospike.com/docs/develop/client/sdk/quickstart)
-   [Behaviors](https://aerospike.com/docs/develop/client/sdk/concepts/behaviors)
-   [Configuration](https://aerospike.com/docs/develop/client/sdk/concepts/configuration)