Distributed FileSystem Interview Questions | JiQuest

add

#

Distributed FileSystem

System design deep dive · HLD

Design a Distributed File System (HDFS-style): full high-level design.

Requirements, back-of-envelope capacity estimation, a high-level design diagram, a deeper deployment architecture diagram, sequence diagrams for block-write replication and failure-triggered re-replication, and an entity-relationship diagram for the metadata model - with the reasoning an interviewer expects behind every box and arrow.

100 PBCluster capacity
128 MBDefault block size
Replication factor
Clientwrite(file) NameNodeblock locations DataNode 1receives block DataNode 2replica copy DataNode 3replica copy pipelined replication, 1→2→3

1. Clarify requirements before drawing any box

A distributed file system trades general-purpose file semantics for extreme scale and durability - the first thing to pin down out loud is that this is write-once/append, large-sequential-file oriented, not a POSIX-compliant random-access filesystem.

Functional requirements

Write a fileSplit a large file into fixed-size blocks and replicate each block across multiple DataNodes.
Read a fileLook up block locations from metadata and stream blocks directly from the nearest/least-loaded DataNode.
Detect failureDetect a dead DataNode via missed heartbeats and re-replicate its blocks elsewhere.
Namespace opsSupport directory-style paths, rename, delete, and permission metadata like a familiar filesystem tree.

Non-functional requirements

High throughput, not low latencyOptimized for large sequential reads/writes (analytics jobs), not small random-access reads.
Durability under multi-node failureData must survive the simultaneous loss of any single rack, not just any single disk.
Horizontal scale to petabytesAdd DataNodes to grow capacity linearly, with no rebalancing downtime.
No metadata single point of failureThe NameNode's availability, not just the data's, must be engineered for.
Explicitly out of scope POSIX-compliant random-byte-range overwrites, sub-second small-file access patterns, and general-purpose file locking are called out as non-goals - this design targets write-once-read-many workloads like the ones the block size and replication strategy below are built around.

2. Back-of-the-envelope capacity estimation

These numbers decide the two hardest constraints in the system: whether the entire block map fits in the NameNode's RAM, and how much cross-rack bandwidth the replication pipeline consumes.

MetricAssumptionResulting estimate
Cluster raw capacity10,000 DataNodes × ~10 TB usable each~100 PB raw cluster capacity
Block count128MB blocks, 100PB stored, replication factor 3~800M unique blocks × 3 = ~2.4B block replicas cluster-wide
NameNode metadata size~150 bytes/block for block map + ~200 bytes/file for inode~800M blocks × 150B ≈ 120GB - must fit entirely in NameNode RAM
Write throughput per client3-way replication pipeline, 1 Gbps NIC per DataNode~100-120 MB/s sustained per client stream
Heartbeat / failure detectionHeartbeat every 3s, DataNode marked stale after 3 missed, dead after 10 missedDetection window of ~30s before re-replication of that node's blocks begins
Why this matters The requirement that ~120GB of block metadata fit in a single NameNode's RAM is the number that forces the large 128MB block size in the first place - a smaller block size (e.g., 4KB, like a local filesystem) would blow up the metadata table by 30,000x and make a single in-memory NameNode impossible.

3. High-level design (HLD)

The HLD names the major components and the one-directional data flow for both the write path (client to DataNodes, with the NameNode only brokering locations) and the read path, without yet committing to HA failover mechanics or rack topology.

ClientHDFS client lib NameNodemetadata, block map Standby NameNodehot failover JournalNodes DataNodesblock storage, ×10,000 Replica set3 copies, rack-aware Heartbeat channelevery 3s + block report Re-replication queueunder-replicated blocks
Metadata planeData planeDurability / replicasControl / monitoring

What each box owns

NameNode (metadata plane)

Holds the entire namespace tree (directories, filenames, permissions) and the block map (which blocks make up each file and which DataNodes hold each block) - entirely in RAM for speed. Critically, file data never flows through the NameNode; it only ever hands out block locations, so it never becomes a data-path bottleneck.

Standby NameNode + JournalNodes

Every namespace mutation is written to a quorum of JournalNodes before being applied, and a hot standby NameNode continuously tails that journal so it can take over within seconds of an active-NameNode failure - eliminating the metadata single point of failure that early distributed file systems were criticized for.

DataNodes (data plane)

Store blocks as ordinary files on local disks, serve read/write requests directly to clients (bypassing the NameNode entirely for the actual bytes), and send a heartbeat plus periodic full block report to the NameNode so it can maintain an accurate view of where every replica lives.

Heartbeat channel and re-replication queue

When a DataNode's heartbeats stop, the NameNode marks it dead and immediately enqueues every block that node held as under-replicated; a background re-replication process then copies each under-replicated block from a surviving replica to a healthy DataNode, restoring the replication factor without any client-visible interruption.

4. Detailed architecture diagram

The architecture diagram adds the piece that most differentiates a real deployment from the HLD: rack topology, and the specific rule that governs where each of the 3 replicas of a block is placed.

Metadata / control plane Active NameNode Standby NameNode JournalNode quorum ×5majority write for durability ZooKeeper (leader election)fencing on failover Rack 1 DataNode d1 (replica A) DataNode d2 (replica B) ... 500 more DataNodessame rack as d1, d2top-of-rack switch Rack 2 (different rack, for durability) DataNode d3 (replica C) ... 9,000 more DataNodesacross ~40 racks totalcross-rack link, WAN-aware Placement policy 2 replicas, same rack, diff nodefast pipeline, survives disk/node loss 1 replica, different rack: survives whole-rack loss Failure detection Heartbeat monitor Under-replicated queue throttled copy so re-replication storms don't saturate the network Erasure-coded cold tier Reed-Solomon 6+3 rarely-accessed files, ~1.5x overhead vs 3x
DecisionChoiceReasoning
Replica placement2 replicas same rack (different nodes), 1 replica different rackBalances write bandwidth (2 nearby replicas fill fast over the top-of-rack switch) against durability (surviving a whole-rack power/network failure).
Metadata architectureSingle active NameNode holding all metadata in RAM, HA standby via JournalNode quorumKeeps every metadata operation a fast in-memory lookup; HA solves the availability risk without sharding metadata, which real deployments avoid unless namespace size forces federation.
Block size128MB (configurable up to 256MB)Large blocks amortize seek overhead for sequential scans and keep the NameNode's metadata table small enough to fit in RAM at petabyte scale.
Cold-data redundancyErasure coding (Reed-Solomon 6+3) for rarely-accessed files instead of 3x replicationCuts storage overhead from 200% to ~50% for data that is read rarely enough that erasure coding's higher reconstruction cost on failure is an acceptable trade.

5. Sequence diagrams for the two critical flows

A sequence diagram here is where an interviewer checks whether replication is understood as a client-driven pipeline (not something the NameNode does), and whether failure detection is separated cleanly from the re-replication it triggers.

5.1 File write with 3-way replication pipeline

Client NameNode DataNode 1 DataNode 2 DataNode 3 1. create(path), request block for next 128MB 2. blockId + ordered DataNode list [1,2,3] 3. open pipeline to DN1 4. forward to DN2 5. forward to DN3 6. ack 7. ack 8. ack (block durable on all 3) 9. block report (async, periodic)

Bytes flow client → DN1 → DN2 → DN3 in a single forward pipeline rather than the client uploading three separate copies - this uses the client's upload bandwidth once instead of three times. The NameNode is only consulted once at the start (step 1-2) to choose which three DataNodes should hold this block; it is never in the data path itself, which is exactly why it can serve metadata for the whole cluster from a single process.

5.2 DataNode failure detection and re-replication

DataNode d2 (dies) NameNode Re-replication queue DataNode d7 (healthy) 1. heartbeat stops (crash / network partition) 2. no heartbeat for 10 intervals (~30s) → mark dead 3. enqueue every block d2 held as under-replicated 4. pick source replica (d1) + healthy target (d7) 5. copy block from surviving replica 6. copy complete, ack 7. block map updated: d7 now holds this replica 8. replication factor restored to 3, transparently

Detection (steps 1-2) and remediation (steps 3-7) are deliberately separate stages: the NameNode's only job at failure time is to notice and mark the node dead cheaply, while the actual re-replication work - the expensive part - is handed to a background queue that copies blocks between DataNodes directly, never through the NameNode. This queue is rate-limited so that a single rack failure re-replicating thousands of blocks at once cannot saturate the cluster's cross-rack network - the same throttle referenced in the architecture diagram above.

6. Entity-relationship (ER) diagram and schema

Unlike a typical relational data model, this "schema" lives almost entirely in the NameNode's in-memory structures rather than a disk-backed database - but it still has to answer the same three questions: what uniquely identifies a block, how block-to-file ordering is preserved, and how block-to-DataNode location is tracked and kept current.

files PK file_id BIGINT path VARCHAR owner VARCHAR size_bytes BIGINT replication TINYINT created_at TIMESTAMP blocks PK block_id BIGINT FK file_id BIGINT block_index INT size_bytes INT gen_stamp BIGINT checksum VARCHAR state ENUM (ordered by block_index) datanodes PK datanode_id VARCHAR rack_id VARCHAR capacity_used BIGINT last_heartbeat TIMESTAMP 1N NM one file has many ordered blocks; blocks and datanodes are many-to-many via the block_locations map (replica placements)

Key modeling decisions

The block-to-DataNode map is not persisted directlyIt is rebuilt in the NameNode's memory on startup entirely from DataNode block reports, since it changes too fast (every heartbeat cycle) to durably persist as its own source of truth.
blocks.block_index preserves file orderingA file's bytes are the concatenation of its blocks in block_index order - there is no other way to reconstruct byte offsets.
gen_stamp (generation stamp) guards against stale replicasIf a replica is written concurrently with a lease recovery after a client crash, gen_stamp lets the NameNode discard the older, possibly-truncated copy.
datanodes.last_heartbeat drives failure detection directlyIt's an in-memory field checked by a periodic sweep, not a query pattern that ever needs a durable index.
Storage choiceUse whenWatch out for
In-memory NameNode structures, journaled to disk/quorumMetadata operations must be sub-millisecond and the whole namespace must fit in one process's RAM.Namespace size is capped by a single NameNode's RAM - very large clusters need HDFS Federation (multiple independent NameNodes, each owning a namespace slice) rather than a bigger box.
Relational DB for the namespace (an alternative some object stores take)You want ad-hoc queries over file metadata (find all files by owner, by size) without exporting fsimage.Adds a network hop to every metadata operation, which is exactly the latency HDFS's design avoids by keeping metadata in-process.

7. Deep dives interviewers actually probe

Why use a large block size (128-256MB) instead of the 4KB blocks a local filesystem uses?

Two independent reasons stack together: first, large blocks amortize the seek/disk-head-movement overhead of sequential scans, which is the dominant access pattern for the analytics jobs this system targets. Second, and more decisive at scale, a smaller block size would multiply the number of metadata entries the NameNode must hold in RAM by tens of thousands - at 4KB blocks, the 800M blocks in the capacity table above become on the order of 25 trillion, which no single process's memory could ever hold.

Why is rack-aware placement (2 replicas same rack, 1 different rack) the default, not 3 different racks?

Three different racks would maximize durability but pay for it on every single write: two of the three replica copies would have to cross the (slower, often oversubscribed) inter-rack network. Two-same-rack-one-different is the balance point - the write pipeline's first two hops stay on the fast top-of-rack switch, while the third hop still guarantees the file survives losing an entire rack (power, top-of-rack switch, or a whole row of hardware failing together).

How does the NameNode's metadata scale past what fits in one machine's RAM?

HDFS Federation: instead of sharding the block map (which would require every read to know which shard owns a given block ahead of time, defeating the point), the namespace itself is partitioned into independent volumes, each with its own NameNode, while all NameNodes share the same pool of DataNodes underneath. A client's path prefix determines which NameNode to talk to - this is closer to horizontally partitioning by directory tree than by hash, which keeps directory-level operations (rename, permissions) cheap within a single NameNode.

What consistency model does this actually provide - can a reader see a partial write?

The classic model is write-once-read-many with no in-place random writes: a file being written is not visible to readers as a complete file until it's explicitly closed, though newer versions do expose a stream of already-flushed bytes to concurrent readers. There is no update-in-place semantic at all - "modifying" a file means writing a new file (or, in append-only mode, appending new blocks) - which is a deliberate simplification that removes the entire class of concurrent-writer conflict resolution a POSIX filesystem has to solve.

What's the single biggest bottleneck as the cluster scales 10x?

Not raw storage or DataNode count - those scale close to linearly by adding more nodes. The real bottleneck is the single active NameNode's metadata throughput and RAM ceiling: every namespace operation (open, create, rename, list) still funnels through one process's lock, and its RAM caps total addressable blocks. That's solved either by Federation (splitting the namespace across multiple NameNodes) or by moving to a fully disaggregated metadata service that shards the block map itself - a much larger architectural change that trades the simplicity of "one process holds the whole namespace" for horizontal metadata scalability.

8. Summary: what a strong answer covers

Named write-once-read-many as the workload, up frontJustified block size from the metadata-RAM constraintKept the NameNode out of the data path Explained rack-aware placement's trade-off explicitlySeparated failure detection from re-replicationNamed Federation as the metadata scaling answer
Interview tip The strongest signal in a distributed-file-system interview is connecting the block size decision back to the metadata capacity constraint unprompted - it shows you understand that the NameNode's RAM, not disk space, is usually the first thing to run out at scale.
No comments
Leave a Comment