Skip to content

Session store

For the complete documentation index see: llms.txt

All documentation pages available in markdown.

Build a high-performance session store for web applications using the Developer SDK.

Use case

Store user session data with:

  • Sub-millisecond reads for every page load
  • Automatic expiration (TTL)
  • High write throughput for session updates

Quick implementation

import com.aerospike.client.sdk.AerospikeException;
import com.aerospike.client.sdk.Cluster;
import com.aerospike.client.sdk.DataSet;
import com.aerospike.client.sdk.RecordResult;
import com.aerospike.client.sdk.RecordStream;
import com.aerospike.client.sdk.ResultCode;
import com.aerospike.client.sdk.Session;
import com.aerospike.client.sdk.policy.Behavior;
import java.util.Map;
import java.util.Optional;
public class SessionStore {
private final Session session;
private final DataSet sessions;
private final int ttlSeconds;
public SessionStore(Cluster cluster, int ttlSeconds) {
this.session = cluster.createSession(Behavior.DEFAULT);
this.sessions = DataSet.of("test", "sessions");
this.ttlSeconds = ttlSeconds;
}
public void save(String sessionId, Map<String, Object> data) {
try {
session.upsert(sessions.id(sessionId))
.bin("data").setTo(data)
.expireRecordAfterSeconds(ttlSeconds)
.execute();
} catch (AerospikeException e) {
// Some local/dev server policies disallow TTL updates (FailForbidden).
if (e.getResultCode() != ResultCode.FAIL_FORBIDDEN) {
throw e;
}
session.upsert(sessions.id(sessionId))
.bin("data").setTo(data)
.execute();
}
}
public Optional<Map<String, Object>> get(String sessionId) {
RecordStream stream = session.query(sessions.id(sessionId)).execute();
Optional<Map<String, Object>> out = stream.getFirst()
.filter(RecordResult::isOk)
.map(RecordResult::recordOrThrow)
.map(r -> (Map<String, Object>) r.bins.get("data"));
stream.close();
return out;
}
public void delete(String sessionId) {
session.delete(sessions.id(sessionId)).execute();
}
public void touch(String sessionId) {
try {
session.touch(sessions.id(sessionId))
.expireRecordAfterSeconds(ttlSeconds)
.execute();
} catch (AerospikeException e) {
if (e.getResultCode() != ResultCode.FAIL_FORBIDDEN) {
throw e;
}
}
}
}

📖 API reference: Cluster.createSession(Behavior) | DataSet.of(...) | Session.upsert(DataSet) | Session.upsert(Key) | Session.delete(Key) | Session.touch(Key) | Session.query(Key) | ChainableOperationBuilder.bin(...) | ChainableQueryBuilder.bin(...) | ChainableQueryBuilder.execute() | RecordStream.getFirst() | RecordStream.close() | RecordResult.isOk() | AerospikeException

Usage

import com.aerospike.client.sdk.Cluster;
import com.aerospike.client.sdk.ClusterDefinition;
import java.util.Map;
import java.util.Optional;
try (Cluster cluster = new ClusterDefinition("localhost", 3000).connect()) {
SessionStore store = new SessionStore(cluster, 3600); // 1 hour TTL
// Save session
store.save("sess-abc123", Map.of(
"userId", "user-1",
"role", "admin",
"loginTime", System.currentTimeMillis()
));
// Get session
Optional<Map<String, Object>> session = store.get("sess-abc123");
System.out.println("Loaded session: " + session.orElse(Map.of()));
// Extend session on activity
store.touch("sess-abc123");
// Logout
store.delete("sess-abc123");
}

📖 API reference: ClusterDefinition(String,int) | ClusterDefinition.connect() | Cluster.close()

Complete example

import com.aerospike.client.sdk.AerospikeException;
import com.aerospike.client.sdk.Cluster;
import com.aerospike.client.sdk.ClusterDefinition;
import com.aerospike.client.sdk.DataSet;
import com.aerospike.client.sdk.RecordResult;
import com.aerospike.client.sdk.RecordStream;
import com.aerospike.client.sdk.ResultCode;
import com.aerospike.client.sdk.Session;
import com.aerospike.client.sdk.policy.Behavior;
import java.util.Map;
import java.util.Optional;
public class SessionStoreExample {
static class SessionStore {
private final Session session;
private final DataSet sessions;
private final int ttlSeconds;
SessionStore(Cluster cluster, int ttlSeconds) {
this.session = cluster.createSession(Behavior.DEFAULT);
this.sessions = DataSet.of("test", "sessions");
this.ttlSeconds = ttlSeconds;
}
void save(String sessionId, Map<String, Object> data) {
try {
session.upsert(sessions.id(sessionId))
.bin("data").setTo(data)
.expireRecordAfterSeconds(ttlSeconds)
.execute();
} catch (AerospikeException e) {
// Some local/dev server policies disallow TTL updates (FailForbidden).
if (e.getResultCode() != ResultCode.FAIL_FORBIDDEN) {
throw e;
}
session.upsert(sessions.id(sessionId))
.bin("data").setTo(data)
.execute();
}
}
Optional<Map<String, Object>> get(String sessionId) {
RecordStream stream = session.query(sessions.id(sessionId)).execute();
try {
return stream.getFirst()
.filter(RecordResult::isOk)
.map(RecordResult::recordOrThrow)
.map(r -> (Map<String, Object>) r.bins.get("data"));
} finally {
stream.close();
}
}
void touch(String sessionId) {
try {
session.touch(sessions.id(sessionId))
.expireRecordAfterSeconds(ttlSeconds)
.execute();
} catch (AerospikeException e) {
if (e.getResultCode() != ResultCode.FAIL_FORBIDDEN) {
throw e;
}
}
}
void delete(String sessionId) {
session.delete(sessions.id(sessionId)).execute();
}
}
public static void main(String[] args) {
try (Cluster cluster = new ClusterDefinition("localhost", 3000).connect()) {
SessionStore store = new SessionStore(cluster, 3600); // 1 hour TTL
String sessionId = "sess-complete-1";
store.save(sessionId, Map.of(
"userId", "user-1",
"role", "admin",
"loginTime", System.currentTimeMillis()
));
Optional<Map<String, Object>> loaded = store.get(sessionId);
System.out.println("Loaded session: " + loaded.orElse(Map.of()));
store.touch(sessionId);
store.delete(sessionId);
}
}
}

📖 API reference: ClusterDefinition(String,int) | ClusterDefinition.connect() | Cluster.createSession(Behavior) | Cluster.close() | DataSet.of(...) | Session.upsert(DataSet) | Session.upsert(Key) | Session.delete(Key) | Session.touch(Key) | Session.query(Key) | ChainableOperationBuilder.bin(...) | ChainableQueryBuilder.bin(...) | ChainableQueryBuilder.execute() | RecordStream.getFirst() | RecordStream.close() | RecordResult.isOk() | AerospikeException

Expected output

Loaded session: {user_id=user-1, role=admin, login_time=<timestamp>}

Performance tips

  1. Use Behavior.DEFAULT as a safe starting point for session workloads
  2. Set appropriate TTL to auto-expire inactive sessions
  3. Use touch() to extend TTL on user activity without rewriting data

Next steps