SD System Design In Depth
0%
lesson system-designgeospatialredis

Redis GEO hot path

Module 5.3: Geospatial Indexing & Proximity Search Updated Sep 18, 2026
📄 Cheat Sheet
How Redis powers Geospatial Queries using GeoHash Algorithm | Redis Internals
Arpit Bhayani How Redis powers Geospatial Queries using GeoHash Algorithm | Redis Internals Watch on YouTube ↗

Explains exactly how Redis GEO encodes 52-bit geohashes into sorted-set scores and turns radius queries into score-range scans, straight from the internals.

0:00 / --:--

Leveraging Redis for Fast Geospatial Queries

When you need to track dynamic points of interest—such as moving vehicles in a ride-sharing app or real-time delivery tracking—traditional disk-based databases like PostGIS may struggle with the high write throughput. This is where Redis GEO commands shine.

How Redis GEO Works

Under the hood, Redis GEO utilizes Sorted Sets (ZSET). When you add a geospatial point using GEOADD, Redis calculates a 52-bit Geohash for the latitude and longitude, and uses this Geohash as the score for the sorted set. This allows Redis to store and retrieve locations rapidly in memory.

Key Commands

  • GEOADD key longitude latitude member: Adds a location to the index.
  • GEODIST key member1 member2 [unit]: Calculates the distance between two members.
  • GEOSEARCH key [FROMLONLAT|FROMMEMBER] [BYRADIUS|BYBOX]: The modern way to query for members within a specific radius or bounding box.

Handling High Write Throughput

In a system like Uber, millions of drivers send location updates every few seconds. To handle this:

  1. Sharding: You cannot store all global locations in a single Redis node. Shard the Redis cluster geographically (e.g., one shard per city or country).
  2. Expiry: Redis key TTL applies to the whole GEO sorted set, not one member. Store per-driver freshness separately and remove stale members with a sweeper or atomic maintenance script; every query must reject candidates older than its freshness limit.
  3. Batching: Use Redis pipelines to batch GEOADD commands from the ingestion service to the Redis nodes.

Example of adding a driver and searching for nearby drivers:

GEOADD drivers -122.4194 37.7749 "driver123"
GEOSEARCH drivers FROMLONLAT -122.4194 37.7749 BYRADIUS 5 km WITHDIST

Worked example: one million active drivers

  • Each driver reports every 4 seconds: 250,000 GEOADD per second globally.
  • Shard by city: a big city with 50,000 active drivers produces 12,500 writes per second to its key, well within a single Redis primary when pipelined.
  • Memory: a sorted-set entry with a short member name costs roughly 60 to 100 bytes including the skiplist and hash overhead, so 1 million drivers is on the order of 100 MB. Memory is not the bottleneck; write rate and hot keys are.
  • Queries: a rider search is GEOSEARCH with a 3 km radius. Its cost is O(N + log M), where N is the number of members in the grid-aligned area scanned around the circle and M is the set size, so dense downtown queries cost more than suburban ones.

Freshness without per-member TTL

Keep two keys per city: drivers:geo:sf (GEO) and drivers:seen:sf (sorted set scored by last update time). On each update: GEOADD drivers:geo:sf -122.4194 37.7749 d123 and ZADD drivers:seen:sf 1727700000 d123. A sweeper every few seconds runs a Lua script that reads ZRANGEBYSCORE drivers:seen:sf -inf now_minus_30 and removes those members from both keys atomically. Queries still check last-seen for each result, because a sweep can lag.

Options for the hot location store

OptionWrite rateQueryWeakness
Redis GEO per cityVery highGEOSEARCH radius or boxManual staleness; hot cities need sub-sharding
Redis hashes keyed by H3 or S2 cellVery highRead the k-ring of cells, filterMore client logic; easy to shard by cell
PostGIS with GiSTModerate; each update rewrites an index entryRich SQL and polygonsIndex churn and vacuum under constant updates
Custom in-memory serviceHighestAnythingYou build replication and failover

Operational notes

  • Redis GEO accepts latitudes only between about -85.05 and 85.05 degrees (the Web Mercator limit).
  • Replicas can serve reads to spread query load; accept that they lag slightly.
  • After a failover, positions refill within one reporting interval, so treat Redis as rebuildable soft state and keep the durable trip record elsewhere.
Check yourself Question 1 of 3
No per-member expiry recall
From: Leveraging Redis for Fast Geospatial Queries

A driver's app crashes and stops sending locations. Why can you not simply set a TTL on that driver in the Redis GEO index?

Key Takeaways

Redis GEO uses Geohashes stored in Sorted Sets.
It is optimized for low-latency, high-throughput in-memory queries.
Regional partitioning can limit working sets, but boundary queries, hot cities, failover, and cross-region movement need explicit routing and rebalancing.
Was this lesson helpful? Spot an issue or have a suggestion? Let us know on GitHub.
Report an issue