Grab has cut production read latency by roughly 50% after switching its Counter Service storage backend from a wide-column database to Aerospike, according to a case study published by InfoQ this week. The ride-hailing company's anti-fraud platform handles tens of thousands of queries every second—around one billion requests daily—and needed a system that could keep pace without breaking the budget. The redesign also shrank on-disk data from approximately 3 terabytes down to 1 terabyte and lowered cost per node by 45% to 50%.
The original architecture stored time-windowed counts—such as recent ride requests or failed payment tries—as separate rows for 15-minute, hourly, and daily intervals. Every incoming event forced three parallel reads, an in-memory addition, and a batch write, totaling four network round trips per transaction. Grab's new data model consolidates all time buckets for a given counter and granularity into a single record holding a timestamp-ordered map, using Aerospike's atomic map increment operation for writes and explicitly purging stale entries. That shift dropped record count by more than an order of magnitude, contributing directly to the smaller index and disk footprint.
According to Daniel Lim, an engineering leader at Grab, the team used "dual read-write paths for traffic shadowing and data parity validation with gradual traffic migration." Rather than swap storage implementations in one leap, the company built a storage facade that exposed legacy, Aerospike, and mock back-ends, with configuration switches controlling single-backend, shadow, and split-traffic modes. Shadow reads climbed incrementally from 5% to 20%, then 50%, and finally 100%, with engineers measuring parity through existing metrics before moving live traffic to Aerospike. Grab reports the migration finished without downtime or data integrity problems.
The record-per-bucket model was abandoned because Aerospike keeps roughly 64 bytes of primary-index metadata per record, making record cardinality a major capacity concern at the scale Counter Service required. The read path also changed: the original backend returned paginated rows filtered by time range on the server, while Aerospike returns records containing maps that Grab now filters on the client side. Aerospike's batch API groups multiple record operations into requests sent to database nodes, cutting the number of network calls for the service's multi-key access pattern. During rollout, the team hit snags with the Aerospike Rust client—including its initially synchronous API and DNS handling during cluster replacement—and later adopted the asynchronous client and collaborated with upstream maintainers on the DNS issue before resuming deployment.
The resulting architecture combines a storage abstraction layer, shadow validation, gradual traffic shifting, and a data model built around Aerospike's record and batch access characteristics. Grab's approach underscores that thoughtful traffic shadowing and incremental rollout can unlock major performance and cost gains while protecting service reliability. For platform engineers weighing similar migrations, the lesson is clear: separating storage from business logic and validating parity at every step turns a risky swap into a controlled, reversible experiment. Decoupling storage interfaces may slow initial development, but it preserves optionality when infrastructure decisions need revisiting under pressure.

