Create records
For the complete documentation index see: llms.txt
All documentation pages available in markdown.
Applies to
- Aerospike Developer SDK preview (Java 21+ and Python 3.10+)
- Aerospike Database 6.0 or later unless a section states otherwise
Learn how to create records in Aerospike using the Developer SDK. This guide covers inserting new records, upserting, setting TTL, and working with collection data types (CDTs).
Except where noted, snippets on this page use the imports below. A snippet lists additional import lines only when it needs a type not shown here. When this page includes a Complete example section, that block is fully self-contained with every import required to run it.
import com.aerospike.client.sdk.AerospikeException;import com.aerospike.client.sdk.DataSet;import com.aerospike.client.sdk.RecordResult;import com.aerospike.client.sdk.RecordStream;
import java.util.List;import java.util.Map;from aerospike_sdk import Behavior, DataSetfrom aerospike_sdk.exceptions import AerospikeErrorInsert a single record
Use insert() to create a new record. This fails if the record already exists.
DataSet users = DataSet.of("test", "users");
session.insert(users) .bins("name", "email", "age") .id("user-1").values("Alice Smith", "alice@example.com", 28) .execute();📖 API reference:
DataSet.of(...)|Session.insert(DataSet)|OperationObjectBuilder.bins(...)|IdValuesBuilder.id(...)|IdValuesRowBuilder.values(...)|ChainableQueryBuilder.execute()
users = DataSet.of("test", "users")
await session.insert(users.id("user-1")).put( {"name": "Alice Smith", "email": "alice@example.com", "age": 28}).execute()📖 API reference:
DataSet.of()|DataSet.id()|Session.insert()|WriteSegmentBuilder.put()|WriteSegmentBuilder.execute()
Upsert (insert or update)
Use upsert() when you want to create a record if it doesn’t exist, or update it if it does.
DataSet users = DataSet.of("test", "users");
// Creates or updates the recordsession.upsert(users) .bins("name", "email", "age") .id("user-1").values("Alice Smith", "alice.smith@example.com", 29) .execute();📖 API reference:
Session.upsert(DataSet)|OperationObjectBuilder.bins(...)|IdValuesBuilder.id(...)|IdValuesRowBuilder.values(...)|ChainableQueryBuilder.execute()
users = DataSet.of("test", "users")
# Creates or updates the recordawait session.upsert(users.id("user-1")).put( {"name": "Alice Smith", "email": "alice.smith@example.com", "age": 29}).execute()📖 API reference:
DataSet.of()|DataSet.id()|Session.upsert()|WriteSegmentBuilder.put()|WriteSegmentBuilder.execute()
Insert vs upsert vs other operations
| Method | Record Exists | Record Doesn’t Exist | Merges with Existing Data |
|---|---|---|---|
insert() | ❌ Fails with error | ✅ Creates record | Not Applicable |
upsert() | ✅ Updates record | ✅ Creates record | ✅ Yes |
update() | ✅ Updates record | ❌ Fails with error | ✅ Yes |
replace() | ✅ Updates record | ✅ Creates record | ❌ No |
replaceIfExists() / replace_if_exists() | ✅ Updates record | ❌ Fails with error | ❌ No |
The table above describes single-key behavior. Batch verbs (session.batch().<verb>(key)) carry the same per-verb existence semantics on the wire — insert requires absent, update requires existing, etc. — so per-key failures surface as non-OK rows in the returned stream.
Rule of thumb: Use insert() when you expect the record to be new and want to catch duplicates. Use upsert() when you don’t care whether it exists.
Set time-to-live (TTL)
Records can automatically expire after a specified duration, or at a specified time:
// Additional imports for this example:import java.time.Duration;import java.time.LocalDateTime;
DataSet users = DataSet.of("test", "users");
// Record expires in 1 hourtry { session.insert(users) .bins("token", "user_id") .id("session-token").values("abc123", "user-1") .expireRecordAfter(Duration.ofHours(1)) .execute();} catch (AerospikeException e) { // Can fail with "Operation not allowed at this time" when TTL prerequisites are not met. System.err.println("TTL write failed: " + e.getMessage());}
// Record expires on 1st January, 2030 (UTC)session.insert(users) .bins("name") .id("user-1").values("Alice") .expireRecordAt(LocalDateTime.of(2030,1,1,0,0,0)) .execute();
// Record never expires (override namespace default)session.insert(users.id("permanent-user")) .bin("name").setTo("System Admin") .neverExpire() .execute();📖 API reference:
DataSet.id(...)|Session.insert(DataSet)|OperationObjectBuilder.bins(...)|IdValuesBuilder.id(...)|IdValuesRowBuilder.values(...)|ChainableQueryBuilder.bin(...)|ChainableQueryBuilder.execute()|AerospikeException
users = DataSet.of("test", "users")
# Record expires in 1 hourtry: await session.insert(users.id("session-token")).put( {"token": "abc123", "user_id": "user-1"} ).expire_record_after_seconds(3600).execute()except AerospikeError as e: # Can fail with "Operation not allowed at this time" when TTL prerequisites are not met. print(f"TTL write failed: {e}")
# Record expires in 30 daysawait session.insert(users.id("user-1")).put( {"name": "Alice"}).expire_record_after_seconds(30 * 24 * 3600).execute()
# Record never expires (override namespace default)await session.insert(users.id("permanent-user")).put( {"name": "System Admin"}).never_expire().execute()📖 API reference:
DataSet.of()|DataSet.id()|Session.insert()|WriteSegmentBuilder.put()|WriteSegmentBuilder.expire_record_after_seconds()|WriteSegmentBuilder.never_expire()|WriteSegmentBuilder.execute()|AerospikeError
Store the user key
By default, Aerospike only stores a digest (hash) of the key. To retrieve
the original key later, enable send-key on the behavior used by the session
— sendKey(true) in Java, send_key=True in Python:
DataSet users = DataSet.of("test", "users");
Behavior sendKeyBehavior = Behavior.DEFAULT.deriveWithChanges("sendKey", builder -> builder.on(Selectors.all(), op -> op.sendKey(true)));
Session session = cluster.createSession(sendKeyBehavior);
session.upsert(users) .bins("name") .id("user-12345").values("Alice") .execute();
// Later, when scanning the set:session.query(users) .execute() .forEach(result -> System.out.printf("key: %s\n", result.key().userKey) // user-12345 );📖 API reference:
Cluster.createSession(Behavior)|DataSet.of(...)|Session.upsert(DataSet)|Session.query(DataSet)|OperationObjectBuilder.bins(...)|IdValuesBuilder.id(...)|IdValuesRowBuilder.values(...)|ChainableQueryBuilder.execute()|RecordStream.forEach(...)|RecordResult.key()
users = DataSet.of("test", "users")
send_key_behavior = Behavior.DEFAULT.derive_with_changes("send_key", send_key=True)session = cluster.create_session(send_key_behavior)
await session.upsert(users.id("user-12345")).put({"name": "Alice"}).execute()
# Later, when scanning the set:stream = await session.query(users).execute()async for row in stream: print(row.key.value) # "user-12345"stream.close()📖 API reference:
Cluster.create_session()|Behavior.derive_with_changes()|DataSet.of()|DataSet.id()|Behavior.DEFAULT|Session.query()|Session.upsert()|WriteSegmentBuilder.put()|RecordResult.key|RecordStream.close()|QueryBuilder.execute()|WriteSegmentBuilder.execute()
Create with CDTs
Aerospike supports lists and maps as bin values:
DataSet users = DataSet.of("test", "users");
// List valuessession.insert(users) .bins("name", "tags", "scores") .id("user-1").values( "Alice", List.of("premium", "verified", "active"), List.of(95, 87, 92, 88) ) .execute();
// Map valuessession.insert(users.id("user-2")) .bin("name").setTo("Alice") .bin("preferences").setTo( Map.of("theme", "dark", "language", "en", "notifications", true)) .execute();
// Nested structuressession.insert(users) .bins("name", "address") .id("user-3").values( "Alice", Map.of( "street", "123 Main St", "city", "San Francisco", "coordinates", List.of(37.7749, -122.4194) ) ) .execute();📖 API reference:
DataSet.id(...)|Session.insert(DataSet)|OperationObjectBuilder.bins(...)|IdValuesBuilder.id(...)|IdValuesRowBuilder.values(...)|ChainableQueryBuilder.bin(...)|BinBuilder.setTo(Map)|ChainableQueryBuilder.execute()
users = DataSet.of("test", "users")
# List valuesawait session.insert(users.id("user-1")).put( { "name": "Alice", "tags": ["premium", "verified", "active"], "scores": [95, 87, 92, 88], }).execute()
# Map/dict valuesawait session.insert(users.id("user-2")).put( { "name": "Alice", "preferences": { "theme": "dark", "language": "en", "notifications": True, }, }).execute()
# Nested structuresawait session.insert(users.id("user-3")).put( { "name": "Alice", "address": { "street": "123 Main St", "city": "San Francisco", "coordinates": [37.7749, -122.4194], }, }).execute()📖 API reference:
DataSet.of()|DataSet.id()|Session.insert()|WriteSegmentBuilder.put()|WriteSegmentBuilder.execute()
📖 Learn more: Data Model explains Aerospike’s data types in detail.
Create only if not exists
Use insert() with error handling to implement “create only if not exists” logic:
DataSet users = DataSet.of("test", "users");
try { session.insert(users) .bins("name") .id("user-1").values("Alice") .execute(); System.out.println("User created successfully");} catch (AerospikeException.RecordExistsException e) { System.out.println("User already exists, skipping creation");}📖 API reference:
Session.insert(DataSet)|OperationObjectBuilder.bins(...)|IdValuesBuilder.id(...)|IdValuesRowBuilder.values(...)|ChainableQueryBuilder.execute()|AerospikeException
# Additional imports for this example:from aerospike_sdk.exceptions import ResultCode
users = DataSet.of("test", "users")
try: await session.insert(users.id("user-1")).put({"name": "Alice"}).execute() print("User created successfully")except AerospikeError as e: if e.result_code != ResultCode.KEY_EXISTS_ERROR: raise print("User already exists, skipping creation")📖 API reference:
DataSet.of()|DataSet.id()|Session.insert()|WriteSegmentBuilder.put()|WriteSegmentBuilder.execute()
📖 Learn more: Error Handling covers all exception types.
Batch create
For creating multiple records efficiently, see Batch Operations.
DataSet users = DataSet.of("test", "users");
// Quick preview - see Batch Operations for full detailssession.insert(users) .bins("name") .id("user-1").values("Alice") .id("user-2").values("Bob") .id("user-3").values("Carol") .execute();📖 API reference:
Session.insert(DataSet)|OperationObjectBuilder.bins(...)|IdValuesBuilder.id(...)|IdValuesRowBuilder.values(...)|ChainableQueryBuilder.execute()
users = DataSet.of("test", "users")
# Quick preview - see Batch Operations for full detailsawait ( session.batch() .insert(users.id("user-1")).put({"name": "Alice"}) .insert(users.id("user-2")).put({"name": "Bob"}) .insert(users.id("user-3")).put({"name": "Carol"}) .execute())📖 API reference:
DataSet.of()|DataSet.id()|Session.batch()|BatchOperationBuilder.insert()|BatchKeyOperationBuilder.put()|BatchOperationBuilder.execute()
Complete example
This example is self-contained—it lists every import needed to run standalone.
import com.aerospike.client.sdk.Cluster;import com.aerospike.client.sdk.ClusterDefinition;import com.aerospike.client.sdk.DataSet;import com.aerospike.client.sdk.Session;import com.aerospike.client.sdk.policy.Behavior;import java.util.List;import java.util.Map;
public class CreateRecordsExample { public static void main(String[] args) { try (Cluster cluster = new ClusterDefinition("localhost", 3000).connect()) { Session session = cluster.createSession(Behavior.DEFAULT); DataSet users = DataSet.of("test", "users"); String key = "create-example-user";
// Cleanup so the example is repeatable. session.delete(users.id(key)).execute();
// Simple insert session.insert(users) .bins("name", "email", "age") .id(key).values("Alice Smith", "alice@example.com", 28) .execute();
// Upsert with complex data session.upsert(users) .bins("name", "tags", "preferences") .id(key).values( "Alice Smith", List.of("premium", "verified"), Map.of("theme", "dark") ) .execute();
System.out.println("Records created successfully!"); } }}📖 API reference:
ClusterDefinition(String,int)|ClusterDefinition.connect()|Cluster.createSession(Behavior)|Cluster.close()|DataSet.of(...)|Session.insert(DataSet)|Session.upsert(DataSet)|Session.delete(Key)|OperationObjectBuilder.bins(...)|IdValuesBuilder.id(...)|IdValuesRowBuilder.values(...)|ChainableQueryBuilder.execute()
import asyncio
from aerospike_sdk import Behavior, ClusterDefinition, DataSet
async def main(): async with await ClusterDefinition("localhost", 3000).connect() as cluster: session = cluster.create_session(Behavior.DEFAULT) users = DataSet.of("test", "users") key = users.id("create-example-user")
# Cleanup so the example is repeatable. await session.delete(key).execute()
# Simple insert await session.insert(key).put( {"name": "Alice Smith", "email": "alice@example.com", "age": 28} ).execute()
# Upsert with complex data await session.upsert(key).put( { "name": "Alice Smith", "tags": ["premium", "verified"], "preferences": {"theme": "dark"}, } ).execute()
print("Records created successfully!")
if __name__ == "__main__": asyncio.run(main())📖 API reference:
ClusterDefinition|ClusterDefinition.connect()|Cluster.create_session()|DataSet.of()|DataSet.id()|Behavior.DEFAULT|Session.upsert()|Session.insert()|Session.delete()|WriteSegmentBuilder.put()|WriteSegmentBuilder.execute()
API reference summary
| Method | Description |
|---|---|
insert() | Create a new record (fails if exists) |
upsert() | Create or update a record |
.bins(name1, name2, ...).id(...).values(...) (Java) · .put({...}) (Python) | Set bin values |
.expireRecordAfter(duration) (Java) · .expire_record_after_seconds(seconds) (Python) | Set time-to-live |
.expireRecordAt(localDateTime) (Java) · Python equivalent coming soon | Expire records at a wall-clock time |
.neverExpire() (Java) · .never_expire() (Python) | Pin record TTL to never expire |
Next steps
Read Records
Retrieve the records you’ve created.
Update Records
Modify existing records and bins.
Batch Operations
Create multiple records efficiently.
Data Model
Understand namespaces, sets, and bins.