AlgoMaster Logo

Data Structures for Scale

High Priority7 min readUpdated July 4, 2026
AI Mock Interview

Practice this topic in a realistic system design interview

Listen to this chapter
Unlock Audio

A web crawler may track billions of URLs. A ride-sharing app may search for nearby drivers across an entire city. A database may keep copies of the same data on many machines and need to check whether those copies still match.

Workloads like these push past what everyday data structures were built for.

Hash sets, B-trees, and sorted arrays are excellent tools. The problem is not that they are bad. The problem is that they usually assume the data fits on one machine, memory is available, and exact answers are affordable.

At billions of items, those assumptions start to break. Sometimes the system needs to save memory. Sometimes it needs to avoid network traffic. Sometimes it needs to answer "close enough" quickly instead of answering exactly slowly.

This section covers eleven data structures that show up in real large-scale systems. They trade a little accuracy, flexibility, or simplicity for big wins in memory, speed, or keeping machines in sync.

1. Why General-Purpose Structures Are Not Enough

A HashSet<String> is fine for a few million entries. A balanced tree is good when you need sorted data. A sorted array works well when data changes rarely and binary search is enough.

But these structures often rely on three assumptions that break in large systems.

AssumptionWhy It Breaks at Scale
Data fits in memoryA billion URL strings can take tens of gigabytes after keys, hash-table overhead, and spare capacity
Every answer must be exactMany systems only need a fast estimate or a quick "definitely not here" check
One machine owns the dataLarge systems split data across machines, so summaries must be easy to combine

Specialized structures replace one expensive assumption with something cheaper.

The cost they reduce is usually not raw CPU. It is memory, lookup time, write pressure, network traffic, or the work needed to keep machines in sync.

The eleven structures in this section fit into four families:

FamilyStructuresProblem SolvedTrade-off
Probabilistic / SketchBloom Filter, Cuckoo Filter, HyperLogLog, Count-Min Sketch, MinHashAnswer "seen?", "how many?", "how often?", or "how similar?" using small memoryAnswers can be approximate
Spatial / GeographicGeohash, S2, H3, Quad Tree, R-TreeFind nearby points, regions, or shapes without scanning everythingUseful mainly for location and geometry
Ordered + ConcurrentSkip ListKeep sorted data fast to read and update while writes are happeningBalance is probabilistic, not guaranteed every time
VerificationMerkle TreeFind differences between large copies of data without comparing every recordBoth sides must hash and order data the same way

The rest of this chapter walks through each family.

2. Family 1: Probabilistic and Sketch Structures

Probabilistic structures answer useful questions without storing every item.

They answer questions like:

  • Have we seen this item before?
  • How many distinct items did we see?
  • How often did this item appear?
  • How similar are these two sets?

They do this by turning inputs into bits, fingerprints, or small counters. They cannot rebuild the original items later. In return, they use far less memory.

StructureQuestionOutput
Bloom FilterIs this item probably in the set?Definitely no, or probably yes
Cuckoo FilterSame question, but with deletes?Probably present, definitely absent, and supports deletion
HyperLogLogHow many distinct items did we see?Approximate distinct count
Count-Min SketchHow often did this item appear?Approximate count, possibly too high
MinHashHow similar are these two sets?Approximate similarity score

The memory difference can be large enough to change the product.

A HashSet of one billion 20-byte identifiers can take tens of gigabytes after hash-table overhead.

A Bloom Filter at a 1% false-positive rate for the same workload uses about 1.2 GB. A HyperLogLog estimating distinct counts uses around 12 KB regardless of whether it sees a million or a billion items.

That is why these structures appear in systems that handle huge or never-ending inputs:

  • LSM-tree storage engines keep a Bloom Filter per SST file to skip files that cannot contain a key
  • CDNs and caches use Bloom Filters to avoid lookups for keys unlikely to be present
  • Analytics tools use HyperLogLog for distinct-user counts over rolling windows
  • Stream processing uses Count-Min Sketch to find high-frequency items
  • Search and deduplication uses MinHash to find near-duplicate documents

The answer is not always exact. The application must be able to tolerate false positives, counts that are a little too high, or small similarity errors.

3. Family 2: Spatial and Geographic Structures

Spatial problems are about location and shape. They do not fit cleanly into a normal single-column index.

A B-tree on latitude and a separate B-tree on longitude cannot efficiently answer:

Find all restaurants within 2 km of this location.

The reason is simple: latitude and longitude only make sense together. Two separate indexes do not understand that combined point.

Spatial structures index data by location, region, or shape. They make nearby searches, map-box searches, and shape intersection queries fast by ruling out large areas early.

Here is where each one fits:

StructureBest ForTrade-off
GeohashStoring locations as strings and searching by prefixRectangular cells can behave oddly near poles and boundaries
S2Global geometry, polygons, and precise spatial relationshipsMore complex and usually used through a library
H3Hexagon-based maps, nearby-cell analysis, and supply-demand analyticsCells do not line up with city, state, or country borders
Quad TreeIn-memory point data in a known areaPerformance depends on how points are spread out
R-TreeDatabase indexes for rectangles, polygons, and shapesOverlapping regions can make searches visit multiple branches

A ride-sharing service cannot scan every driver's coordinates for every rider request. A mapping product cannot test every road shape against the visible map area on every pan or zoom.

Spatial indexes make those queries practical by ruling out large regions early. They power PostGIS, MongoDB's 2dsphere index, Elasticsearch geo queries, and the cell-based dispatch indexes used inside ride-sharing systems.

The choice usually depends on where the structure lives and what kind of query the system runs.

  • A string in a SQL column often points to Geohash.
  • A cell ID that moves through caches, queues, and analytics often points to S2 or H3.
  • An in-memory index for points in a fixed area often points to a Quad Tree.
  • A database-backed index for shapes often points to an R-Tree.

4. Family 3: Ordered Structures Under Concurrency

Storage engines, in-memory indexes, and ordered caches often need three things at the same time:

  • fast lookups
  • fast updates
  • fast range scans

Balanced binary search trees support these operations, but their rebalancing logic can be hard to make fast when many threads are writing at once.

Skip Lists solve the problem with a simpler idea: add higher-level "express lanes" above a sorted linked list. Searches use the upper lanes to skip over large parts of the list. Updates usually touch only a few nearby nodes.

The lookup starts in the highest lane. When the next jump would go past the target, it drops down one lane and keeps going.

Skip Lists give expected O(log n) lookups, inserts, and deletes while keeping the implementation relatively small. That simplicity is one reason they work well under concurrent writes.

They appear in LSM-tree memtables such as RocksDB and LevelDB. Redis sorted sets pair a skip list with a hash table, giving ordered range queries plus fast membership checks. Skip Lists also show up in embedded indexes where simple, reliable implementation matters.

The trade-off is that balance is random. Bad cases are unlikely, but not impossible. If a system needs strict worst-case guarantees, a balanced tree may still be the better choice.

5. Family 4: Verification Structures

Distributed systems often keep more than one copy of the same data. Over time, those copies can drift apart.

That can happen during network partitions, failed writes, delayed replication, or backup jobs. The system needs a cheap way to answer:

Are these two copies identical? If not, which small part is different?

A naive comparison sends every record across the network and compares the bytes. That is fine for small datasets. It is painful for terabytes of data.

A Merkle Tree organizes hashes into a tree:

  • Each leaf hashes one block or range of data.
  • Each internal node hashes its child hashes.
  • The root hash summarizes the entire dataset in one fixed-size value.

Two replicas compare their root hashes first. If the roots match, the datasets match. If the roots differ, the systems walk down only the branches whose hashes disagree until they find the changed blocks.

Merkle Trees show up in many places:

  • Dynamo-style databases such as Cassandra and Riak use them to compare and repair replicas.
  • Git uses a Merkle-like structure so repositories can detect missing objects quickly.
  • Blockchains use Merkle roots so lightweight clients can verify transactions without downloading every transaction.
  • Content-addressed storage uses them to detect changes and avoid storing duplicate data.

The catch is that both sides must build the tree the same way. They must agree on hashing, ordering, byte format, and tree shape. If they disagree on any of those, the trees may look different even when the data is logically the same.

6. Common Misuses

A few common mistakes are worth calling out before the deep-dive chapters:

  • A Bloom Filter cannot serve as a primary cache. It returns membership, not the value.
  • HyperLogLog cannot list the distinct items. It only counts them.
  • Count-Min Sketch can count too high, not too low. That is safe only when overcounting is acceptable.
  • Geohash queries near the poles need care because cells become distorted.
  • Skip Lists do not give strict worst-case latency guarantees.
  • A Merkle Tree comparison fails if the two systems order or encode data differently.

7. Where These Structures Live in a Real System

A single production system may use several of these structures in different layers.

None of these structures replaces hash tables or B-trees everywhere. They solve specific pressure points where the main cost is memory, network traffic, location search, concurrent writes, or replica comparison.

Summary

General-purpose data structures stop being enough when the data is too large, too distributed, too location-heavy, or too expensive to compare directly.

The four families in this section handle those pressures:

  • Probabilistic and sketch structures trade exact answers for much smaller memory.
  • Spatial and geographic structures make location and shape queries fast.
  • Ordered and concurrent structures keep sorted data fast while writes are happening.
  • Verification structures use hashes so two systems can find differences without sending all the data.

Each structure gives up being useful for everything so it can become excellent at one specific job.