NEWS

Agoda swaps 72 SQL Server shards for DragonflyDB and cuts latency by 8x

The hotel price cache migration shows how an infrastructure decision reduced P99 latency and simplified the production scaling model.

Agoda swaps 72 SQL Server shards for DragonflyDB and cuts latency by 8x
Image: Redação iMasters

Agoda migrated its hotel price cache (the so-called tier-one Price Cache) from a deployment with 72 Microsoft SQL Server shards to DragonflyDB, an in-memory, Redis-compatible datastore. According to reporting by InfoQ, the cache holds about 1.5 TB of volatile price data and absorbs roughly 300,000 reads and 1.5 million writes per second. After the switch, the company reported an improvement of about 8x in read P99 latency, with DragonflyDB serving around 300,000 requests per second at approximately 8 ms P99.

For those building software in Brazil, the case matters less for the product name and more for the sequence of decisions: how to move off a sharded relational cache without stopping production, how to validate data parity before switching traffic, and how to fail over without a central coordinator. None of this depends on operating at Agoda's scale; it's engineering applicable to any read-heavy service with data that expires.

The bottleneck SQL Server became

The previous architecture required application-level shard routing across the 72 SQL Server shards. Scaling meant hardware increases in predefined increments, plus manual shard remapping and data migration. Agoda doubled its hardware capacity in early 2024 and, even so, was approaching its limits again in less than a year. There was also a separate process just to clean up expired supplier data.

The diagnosis from lead engineer Clarkson Chang is the point where many Brazilian teams will recognize themselves:

It became clear that continuing to add resources to SQL Server was not a viable or cost-effective strategy in the long run.

>

-- Clarkson Chang, lead engineer at Agoda

The practical takeaway here: using a relational database as a cache for a very high write rate exacts a price in operational rigidity. Every expansion becomes a project, and the cost per unit of throughput grows. When the access pattern is essentially key-value with expiration, an in-memory datastore tends to fit the shape of the problem better.

Why DragonflyDB and not just Redis

Agoda didn't rely solely on published benchmarks: it evaluated DragonflyDB against its own workload. The shared-nothing, multithreaded architecture, Redis compatibility, cluster-based scaling, and native key expiration matched a workload that depends heavily on MGET and SET.

To reproduce production before touching production, the team used memtier_benchmark, recreating the real 1-read-to-6-write ratio and MGET operations averaging 10 keys. This is the detail that separates a serious test from a marketing test: instead of running the tool's default benchmark, they modeled the actual service's ratio and operation size.

| Metric | Before (72 SQL Server shards) | After (DragonflyDB) | |---|---|---| | Cached data | ~1.5 TB volatile | ~1.5 TB volatile | | Reads/s | ~300,000 | ~300,000 at ~8 ms P99 | | Writes/s | ~1.5 million | ~1.6 million at ~10 ms P99 | | Read P99 latency | baseline | ~8x lower | | Scaling model | hardware increments + manual shard remap | cluster, 3 shards per cluster |

The migration was incremental, and that's where the lesson is

The most reusable point of the case isn't the latency number, it's the cutover method without downtime. Agoda started with a 1 TB instance just for hot data, but organic growth pushed the dataset close to the 90% memory safety threshold. The response was a design with three shards per cluster, expanded to hold the full 1.5 TB, reaching ~1.6 million writes/s at ~10 ms P99.

Before moving clients, came the dual reads stage: SQL Server kept serving requests while the Price API asynchronously fetched the corresponding data from DragonflyDB. Instead of comparing the entire price payload (expensive and fragile), the team checked two cheap dimensions:

  • supplier counts (supplier counts);
  • price-data lengths (price-data lengths).

The results were emitted as Prometheus metrics. Both dimensions reached more than 99.9% parity before any real traffic was diverted. Only then did Agoda use an A/B experiment to gradually move clients; after a few weeks, 100% of traffic was on DragonflyDB and SQL Server's read and write paths were retired.

This playbook (cheap shadow read, parity metric, traffic A/B, legacy shutdown) is replicable in any datastore swap. The choice to compare integrity proxies instead of the entire object is the kind of decision that avoids wasting time comparing bytes that don't matter.

Failover without a central coordinator

The final change tackled failure handling. Two DragonflyDB clusters, A and B, provide high availability. Instead of a central coordinator deciding who is healthy, each application pod independently compares the cache-hit ratio of the two clusters using five minutes of local observations.

The rule is statistical and symmetric:

  • a significant divergence of 10 percentage points marks a cluster as unreadable;
  • recovery requires the difference to fall within 3 percentage points.

In an outage simulation, about 40 pods detected the failure and entered failover in approximately two minutes, with no manual intervention. The decentralized design avoids the classic single point of failure of the coordinator and removes the dependency on someone pressing a button at 3 a.m.

What remains open

Agoda coupled the datastore swap with production parity checks, controlled traffic migration, explicit cache warming behavior, and decentralized failure detection. The gain wasn't just lower latency: it was a less rigid scaling model and less operational maintenance around stale data and failover.

The material doesn't disclose absolute cost figures or the exact hardware behind the clusters, so the TCO comparison rests on Chang's qualitative statement. It's also worth stating the obvious for anyone copying the recipe: a 1.5 TB in-memory cache has its own RAM cost, and the 90% threshold shows that memory headroom becomes a constant operational variable. For Brazilian services with read-heavy workloads and data that expires (price, availability, feed, session), the value here is the migration playbook and the failover architecture, more than the datastore brand.

Translated from the Brazilian Portuguese original · Read the original