Understanding the SDK API
For the complete documentation index see: 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
import java.time.Duration;import com.aerospike.client.sdk.DataSet;
// Classic Client - verbose, configuration-heavyWritePolicy 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, readableDataSet 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(...)|Key|Session.insert(DataSet)|OperationObjectBuilder.bins(...)|IdValuesBuilder.id(...)|IdValuesRowBuilder.values(...)|ChainableQueryBuilder.execute()
from aerospike_sdk import DataSet
# Classic Client - verbose, configuration-heavypolicy = {"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()|DataSet.id()|Behavior.DEFAULT|Session.insert()|WriteSegmentBuilder.put()|WriteSegmentBuilder.expire_record_after_seconds()|WriteSegmentBuilder.execute()
Method chaining philosophy
Fluent interfaces follow these principles:
- Discoverability: IDE autocomplete guides you through available options
- Readability: Code reads like a sentence describing what it does
- Immutability: Each chain step returns a new builder (no mutation)
- Terminal Operations: Chains end with an action (
execute(), then stream iteration for queries)
Builder pattern integration
The Developer SDK uses builders for complex configuration:
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 clusterSession session = cluster.createSession(Behavior.DEFAULT);📖 API reference:
ClusterDefinition(Host...)|Host(String,int)|Host(String,String,int)|ClusterDefinition.connect()|Cluster.createSession(Behavior)
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 clustersession = cluster.create_session(Behavior.DEFAULT)📖 API reference:
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