NoSQL Databases

Aerospike Explained: The Complete Guide to Real-Time NoSQL at Scale

Achieve microsecond latencies at scale with Aerospike. Learn hybrid memory architecture, strong consistency, cross-datacenter replication, and use cases for AdTech and fraud detection.

JusDB Team
November 29, 2022
5 min read
5035 views

When teams hit the ceiling of what Redis can do — either from memory costs, throughput limitations, or the need for persistent storage without sacrificing sub-millisecond latency — Aerospike is usually where they land. We've migrated several ad-tech clients from Redis clusters that were consuming $40,000/month in RAM to Aerospike deployments on NVMe SSDs at a third of the cost, with better tail latency.

Aerospike isn't a drop-in Redis replacement (different data model, different client protocol), but for specific workloads — real-time bidding, fraud detection, session stores at massive scale, IoT telemetry — nothing else comes close to its performance/cost ratio at high throughput.

TL;DR
  • Aerospike delivers sub-millisecond latency at millions of TPS with data persisted to SSD — not purely in-memory
  • Hybrid Memory Architecture: indexes live in DRAM, data lives on NVMe SSDs — this is why it's cost-effective at scale
  • Best for: real-time bidding, fraud detection, session stores, personalization, IoT — anything needing low latency + durability + massive scale
  • Not for: ad-hoc analytics, complex joins, OLAP workloads — use ClickHouse or StarRocks for those
  • XDR (Cross-Datacenter Replication) enables active-active global deployments that Redis Cluster cannot match

Why Aerospike Exists: The Problem It Solves

In-memory databases like Redis give you the fastest possible reads and writes — but every byte of data has to fit in DRAM. At scale, DRAM is expensive. A Redis cluster storing 1TB of data needs roughly 1TB of DRAM across your fleet, plus replication overhead. At $8–12/GB for server DRAM, that's $8,000–$12,000 just in memory hardware for 1TB of data.

NVMe SSDs store the same data for roughly 10–50× less cost. The trade-off is that SSDs are slower — but modern NVMe SSDs are fast enough that with the right architecture, you can deliver sub-millisecond reads from SSD-resident data. That's Aerospike's core insight: keep indexes in DRAM (indexes are small — typically 64 bytes per record), serve data from NVMe, and use direct I/O to bypass the OS page cache.

The result: Aerospike can store terabytes of data and serve millions of reads per second at P99 latencies under 1ms on commodity NVMe hardware.


Architecture: Hybrid Memory Storage

How data is stored

Aerospike's storage is namespace-level and configurable per namespace:

  • In-memory only: Like Redis — data and indexes both in RAM. Fastest, most expensive. Use for hot caches where data is small and re-generable.
  • Hybrid (index in RAM, data on SSD): The recommended production configuration. Indexes fit in DRAM (64 bytes per record). Data is written directly to NVMe using direct I/O, bypassing the OS page cache for predictable latency.
  • Index on flash (Aerospike 6+): For datasets so large that even 64-byte-per-record index overhead doesn't fit in DRAM. Stores the index on a separate flash device.
code
# aerospike.conf — namespace configuration

namespace users {
  replication-factor 2
  memory-size 8G          # DRAM for indexes and metadata

  storage-engine device {
    device /dev/nvme0n1   # NVMe SSD for data
    write-block-size 128K
    data-in-memory false  # data stays on SSD, not in DRAM cache
    direct-io true        # bypass OS page cache for predictable latency
  }
}

namespace sessions {
  replication-factor 2
  memory-size 32G

  storage-engine memory   # this namespace is fully in-memory (hot cache)
}

Cluster topology

Aerospike uses a shared-nothing, masterless architecture. Every node is equal — there's no primary/secondary relationship. Data is distributed across nodes using a consistent hash partition map. Any node can serve reads and writes for any key, routing internally when needed.

code
# Check cluster health
asinfo -v 'statistics' | grep cluster

# Or with AQL
AQL> show sets
AQL> show namespaces

# Node-level stats
asadm -e "show statistics like cluster_size"

Cross-Datacenter Replication (XDR)

XDR enables active-active replication between clusters in different datacenters. Both clusters accept writes independently, and XDR syncs changes asynchronously. Conflict resolution is configurable (last-write-wins, generation-based, etc.).

This is the feature that makes Aerospike compelling for global ad-tech deployments: a bidder in Tokyo and a bidder in Virginia can both write user profile updates, and XDR reconciles them without a global consensus protocol penalizing every write with cross-region latency.


Data Model

Aerospike's data model differs from Redis and from relational databases:

code
Hierarchy:
  Cluster
  └── Namespace (like a database or keyspace)
      └── Set (like a table — optional, used for grouping records)
          └── Record (identified by a primary key)
              └── Bins (like columns — each record can have different bins)

Example record:
  Namespace: user_data
  Set: profiles
  Key: user:1001
  Bins: {
    name: "Alice Chen",
    plan: "premium",
    last_seen: 1737500000,
    feature_flags: ["ab_test_v2", "new_checkout"]
  }

Supported data types per bin

  • Integer, String, Bytes, Double
  • List, Map (nested structures)
  • GeoJSON (for geospatial queries)
  • HyperLogLog (cardinality estimation, like Redis HLL)

Core Operations

Python client

code
import aerospike

config = {'hosts': [('aerospike-host', 3000)]}
client = aerospike.client(config).connect()

# Write a record
key = ('user_data', 'profiles', 'user:1001')
bins = {
    'name': 'Alice Chen',
    'plan': 'premium',
    'last_seen': 1737500000,
    'feature_flags': ['ab_test_v2', 'new_checkout']
}
# TTL in seconds (0 = use namespace default, -1 = no expiry)
meta = {'ttl': 86400 * 30}  # 30 days

client.put(key, bins, meta)

# Read a record
(key, meta, record) = client.get(key)
print(record['name'])  # Alice Chen

# Read specific bins only (reduces data transfer)
(key, meta, record) = client.select(key, ['name', 'plan'])

# Update a single bin without reading the whole record
client.put(key, {'last_seen': 1737600000})  # partial update

# Atomic counter increment (no read-modify-write needed)
client.increment(key, 'page_views', 1)

# Delete
client.remove(key)

Batch operations (critical for throughput)

code
# Read multiple records in a single network round-trip
keys = [
    ('user_data', 'profiles', f'user:{i}')
    for i in range(1000, 1100)
]

# Batch read — much faster than 100 individual gets
records = client.get_many(keys)

# Write with a policy: update only if record exists (no insert)
policy = {'exists': aerospike.POLICY_EXISTS_UPDATE}
client.put(key, {'plan': 'enterprise'}, {}, policy)

Secondary indexes and queries

code
# Create a secondary index (run once)
client.index_integer_create('user_data', 'profiles', 'account_tier', 'idx_tier')

# Query using the index
from aerospike import predicates as p

query = client.query('user_data', 'profiles')
query.where(p.equals('account_tier', 2))
results = query.results()

# Range query
query.where(p.between('last_seen', 1737000000, 1737600000))

# Note: secondary index queries scan matching records across all nodes
# For high-cardinality filters, this is efficient
# For low-cardinality (e.g., boolean), prefer scan + UDF

Production Configuration

code
# /etc/aerospike/aerospike.conf — production baseline

service {
  paxos-single-replica-limit 1    # minimum nodes for a write quorum
  proto-fd-max 15000               # max file descriptors per node
  work-threads 8                   # match to (CPU cores * 2) roughly
}

network {
  service {
    address any
    port 3000
    access-address 10.0.1.10      # bind to private IP only
  }
  heartbeat {
    mode mesh
    address 10.0.1.10
    port 3002
    mesh-seed-address-port 10.0.1.11 3002
    mesh-seed-address-port 10.0.1.12 3002
    interval 150
    timeout 10
  }
  fabric {
    port 3001
  }
}

namespace user_data {
  replication-factor 2
  default-ttl 30D                  # records expire after 30 days by default
  nsup-period 120                  # eviction scan every 120 seconds

  memory-size 16G                  # DRAM for indexes

  storage-engine device {
    device /dev/nvme0n1
    device /dev/nvme1n1            # stripe across multiple NVMe devices
    write-block-size 128K
    data-in-memory false
    direct-io true
    post-write-queue 256
  }
}

Performance Tuning

Benchmark your NVMe before sizing

code
# Aerospike Certification Tool (ACT) — validates NVMe performance
# Download: https://github.com/aerospike/act
act -d /dev/nvme0n1 -t 3600    # run 1-hour I/O stress test

# Aerospike requires:
# Sequential write bandwidth: > 1 GB/s
# Random read IOPS (4KB): > 100K IOPS for good performance
# Latency at 100% load: P99 < 1ms

# AWS recommended instance types for Aerospike:
# i3.2xlarge (1.9TB NVMe): good starting point
# i3.4xlarge (3.8TB NVMe): for larger datasets
# i3en.xlarge (2.5TB NVMe): better cost per TB

Key metrics to monitor

code
# Real-time node stats
asadm -e "show statistics"

# Key metrics:
# client_read_success / client_read_error  -- read hit rate
# client_write_success / client_write_error
# device_read_tps / device_write_tps       -- SSD throughput
# memory_used_pct                          -- DRAM for indexes (alert > 80%)
# storage_used_pct                         -- SSD (alert > 75%)
# migrate_progress_recv / send             -- data migration (expect during node joins)

# Latency histogram
asadm -e "show latencies"
# Shows P50, P90, P99 for reads, writes, udf, batch
# Alert thresholds: P99 reads > 5ms, P99 writes > 5ms

Aerospike vs Redis: When to Choose Which

Factor Aerospike Redis / Valkey
Data sizeTerabytes (data on SSD)Hundreds of GB (all in RAM)
LatencySub-ms (P99 typically 0.5–2ms)Sub-ms (P99 typically 0.2–1ms in-memory)
ThroughputMillions of TPS with NVMeHundreds of thousands TPS per node
Cost at 1TB+10–50× cheaper than all-RAMVery expensive at multi-TB scale
Data structuresKey-value, lists, maps, geospatialRicher (sorted sets, streams, HLL, etc.)
Multi-datacenterNative XDR active-activeRedis Enterprise Geo (commercial)
Client ecosystemAerospike-specific clientsMassive (redis-py, ioredis, Jedis...)
Best forLarge-scale persistent NoSQL (RTB, fraud, IoT)Caching, pub/sub, smaller datasets, richer data structures

The decision often comes down to data size. If your dataset fits comfortably in RAM and your use case benefits from Redis' rich data structures (sorted sets, streams, pub/sub), stay with Redis/Valkey. If you're managing terabytes of data with sub-millisecond latency requirements and durability, Aerospike is worth the client migration cost.


When NOT to Use Aerospike

  • Small datasets (<50GB): Redis/Valkey is simpler to operate and has a richer ecosystem. Aerospike's complexity pays off at scale.
  • Complex queries and joins: Aerospike is a key-value store. Secondary indexes exist, but multi-table joins, aggregations, and SQL-style queries are not its strength.
  • Analytics workloads: For aggregating billions of events, use ClickHouse or StarRocks. Aerospike is for low-latency point reads and writes, not full-table scans.
  • Teams without NVMe hardware: Aerospike's performance advantage depends heavily on fast NVMe SSDs. On spinning disks or slow SSDs, the latency guarantee disappears.

Working with JusDB on Aerospike

Aerospike deployments have a steeper operational learning curve than Redis or Cassandra — namespace design, NVMe sizing, XDR configuration, and eviction policy tuning all require hands-on experience. Getting these wrong means either paying for too much hardware or hitting unexpected latency spikes under load.

We've designed and operated Aerospike clusters for ad-tech, fintech, and IoT workloads. Common engagements include migrating from over-provisioned Redis clusters, sizing NVMe-backed namespaces for specific throughput and latency targets, and setting up XDR for multi-region active-active deployments.

Our Aerospike consulting includes architecture design, benchmarking with ACT, and production cluster operations. If you're evaluating Aerospike for your workload or troubleshooting an existing deployment, reach out.

Related reading: DynamoDB to Aerospike Migration Case Study | Redis vs Valkey Guide | Aerospike Consulting

Share this article

JusDB Team

Official JusDB content team