Skip to content

Key/Value API

The key/value API provides a distributed, consistent data store for arbitrary binary data organized within namespaces. Built on Raft consensus, all operations guarantee strong consistency across the cluster, ensuring reads always return the most recently committed value.

  • Strong Consistency: All operations are linearizable through Raft consensus
  • Namespace Isolation: Complete tenant separation with per-namespace authentication
  • TTL Support: Automatic key expiration with background cleanup
  • Atomic Operations: Compare-and-swap for optimistic concurrency control
  • High Performance: Microsecond read latency with in-memory caching
  • Durability: All writes replicated across majority of cluster nodes

Creates a new namespace registered to the calling credential. The call is idempotent; requesting an existing namespace succeeds without modifying it.

message CreateNamespaceRequest {
string namespace = 1;
}
message CreateNamespaceResponse {
string namespace = 1;
Status status = 2;
}

Fetches the value for a key. Returns a NOT_FOUND error if the key does not exist.

message GetKeyRequest {
string key = 1;
string namespace = 2;
}
message GetKeyResponse {
string key = 1;
string namespace = 2;
bytes value = 3;
Status status = 4;
}

Stores or updates a key. Optional TTL expiry can be provided in milliseconds. A TTL of 0 means the value never expires. Writes are atomic and overwrite any existing value.

message PutKeyRequest {
string key = 1;
string namespace = 2;
bytes value = 3;
optional uint64 ttl_ms = 4; // Time to live in milliseconds
}
message PutKeyResponse {
string key = 1;
Status status = 2;
}

Removes a key from the namespace. Deleting a missing key is treated as success so the operation is idempotent.

message DeleteKeyRequest {
string key = 1;
string namespace = 2;
}
message DeleteKeyResponse {
string key = 1;
Status status = 2;
}

Returns the names of keys in the namespace. A prefix can be supplied to filter the results and limit restricts the number of keys returned.

message ListKeysRequest {
string prefix = 1;
string namespace = 2;
optional uint64 limit = 3; // Max number of keys to return
}
message ListKeysResponse {
repeated string keys = 1;
Status status = 2;
}

Atomically update a key only if its current value matches the expected bytes. This can be used to implement optimistic concurrency for small payloads.

message CompareAndSwapRequest {
string key = 1;
string namespace = 2;
bytes expected = 3;
bytes newValue = 4;
}
message CompareAndSwapResponse {
string key = 1;
string namespace = 2;
bool swapped = 3;
Status status = 4;
}
import primatomic
# Connect to Primatomic Cloud
client = primatomic.Client("your-workspace.primatomic.com:443",
jwt_token="your-api-token")
# Create namespace and store data
client.create_namespace("myapp")
client.put_key("myapp", "user:123:profile", b'{"name": "Alice", "email": "[email protected]"}')
# Retrieve data
profile = client.get_key("myapp", "user:123:profile")
print(profile.decode('utf-8'))
# Atomic compare-and-swap for optimistic updates
current_value = client.get_key("myapp", "counter")
success = client.compare_and_swap(
namespace="myapp",
key="counter",
expected_value=current_value,
new_value=str(int(current_value) + 1).encode()
)
# List keys with prefix
user_keys = client.list_keys("myapp", prefix="user:", limit=100)
for key in user_keys:
print(f"Found user key: {key}")
# TTL expiration (expire after 1 hour)
client.put_key("myapp", "session:abc123", b"user_data", ttl_ms=3600000)

Coming soon - JavaScript SDK is in development. For early access, contact us.

Common error codes returned by the key/value API:

  • NOT_FOUND: Requested key does not exist in the namespace
  • PERMISSION_DENIED: Invalid credential ID or insufficient namespace access
  • ALREADY_EXISTS: Namespace creation failed because it already exists
  • DEADLINE_EXCEEDED: Operation timeout, typically during cluster unavailability
  • UNAVAILABLE: Cluster is not ready or no leader elected
  • Batch Operations: Use concurrent requests for multiple independent operations
  • Key Design: Choose meaningful prefixes for efficient listing and organization
  • TTL Usage: Prefer TTL over manual deletion for temporary data
  • Size Limits: Key names limited to 1KB, values limited to 16MB per operation
  • Concurrent Access: Use compare-and-swap for conflict resolution instead of explicit locking