Loading...
System Design and AI Engineering, by Roni Das. 980 interactive lessons.
Start LearningSystem design interview guide
Short answer
A unique ID generator gives every new record a number that is never used twice, across many servers, without a central bottleneck. The usual answer is a Snowflake-style 64-bit ID, made inside each app server with no network call. It has 41 bits of milliseconds since a chosen start date (the epoch), a 10-bit machine ID and a 12-bit sequence counter. That is 4,096 IDs per millisecond per machine, up to 1,024 machines, for about 69.7 years. Because time comes first, IDs sort roughly by creation time and new rows go to the end of a database index. Each machine leases its machine ID from etcd or ZooKeeper at startup. If the clock goes backwards, the generator waits or refuses, because reusing a millisecond could make a duplicate. If 128 bits are fine, a UUIDv7 needs no machine IDs and is also time-ordered; a random UUIDv4 scatters inserts across the index.
in this guide
8 parts open to everyone · 3 with a free account · 3 with the course
The question is small enough to finish in one interview, but it touches four hard things. Coordination: how do 500 servers avoid picking the same number without talking to each other on every request? Time: clocks on different machines disagree, and a clock can even jump backwards. Storage: the ID becomes the primary key, the main index of every table, so its size and its order affect every insert. And trade-offs, where you gain one thing by giving up another: there is no single best answer, only the right one for a set of requirements. A weak answer says 'use a UUID' and stops. A strong answer first asks what the ID must do: fit in 64 bits, sort by time, be hard to guess. Then it compares four or five schemes with numbers. It explains each part of the Snowflake layout with arithmetic. And it says exactly what the generator does when the clock goes back or the counter runs out inside one millisecond.
This page is the free part.
₹499 in India$49 everywhere elseonce, for the whole course
The System Design course covers the unique ID generator design across a run of lessons, not one page. These 4 alone are about 152 minutes of step-by-step reading, 1 of them with code you run in the browser, all with a quiz.
Live from the course bench
Real interview questions, live diagrams and measured lab results, pulled at random from the lessons. A new set every time you come back.
Always clarify these in the first 5 minutes of the interview. Do not start drawing boxes until both lists are agreed.
This guide is built on these 6 lessons. Each one teaches one piece of the unique ID generator design above, step by step.
Lifetime access for ₹499 in India or $49 elsewhere. Interactive diagrams, quizzes, and 20 capstone projects to practise on.
This one question is not enough for the interview.
Each question has why it is asked, a full answer, what the interviewer listens for, the follow-ups, the common mistakes and a diagram (268 diagrams in all). A PDF you keep, junior to staff level.
Two courses by the author of this page:
770 lessons · 18 free to read
₹499 in India · $49 elsewhere, once
Get System DesignYou own this course
210 lessons · 10 free to read
₹999 in India · $49 elsewhere, once
Get AI EngineeringYou own this course
Save your progress and get the interview checklist PDF
Every new row needs a name that no other row will ever have. A row is one record in a database table, such as one tweet. A tweet, a photo, an order, a chat message. On one database this is easy: the database counts 1, 2, 3. Now spread the data over 50 databases and 500 app servers. Each of them makes new rows at the same moment, and none of them wants to stop and ask the others. Two servers must never pick the same number, not even once in ten years. The numbers should also sort roughly by time, so asking the database for 'newest first' (a query) is fast and cheap. And they should fit in 64 bits (a bit is one binary digit, 0 or 1), because every index stores them. An index is a sorted list the database uses to find rows fast. Twitter's Snowflake packs all of this into one number: 41 bits of milliseconds, 10 bits of machine number, 12 bits of counter. That is 4,096 IDs per millisecond on each machine, with no network call.
A unique ID generator gives every new record a number that is never used twice, across many servers, with no central bottleneck. First, some terms. A bit is one binary digit, 0 or 1; 64 bits hold any whole number up to about 9.2 billion billion. A BIGINT is the database column type that holds a 64-bit whole number. An epoch is the fixed starting moment that a time count is measured from. The main options are these. A database counter (auto-increment: the database adds 1 for each new row) is simple. But it runs on one machine, so if that machine fails, nobody gets a new ID. Several databases can share the work by stepping: one gives odd numbers, one gives even numbers, which is how Flickr's ticket servers work. A UUID is a 128-bit ID. Version 4 is random, so any machine can make one without asking other machines, but is twice the size of a BIGINT and scatters new rows all over an index. Version 7, defined in RFC 9562 (an official internet standard), puts a 48-bit millisecond timestamp first, so new IDs land next to each other. Twitter's Snowflake builds a 64-bit number from three parts: 41 bits of milliseconds since a chosen epoch, a 10-bit machine ID, and a 12-bit sequence counter. That gives 4,096 IDs per millisecond per machine and about 69.7 years before the time bits run out. Instagram used the same idea inside PostgreSQL, with 13 bits for a shard number (a shard is one of the many databases that together hold the data) and 10 bits for the counter. Segment allocation hands each server a block of numbers from a database, such as 1,000 at a time, so the database is asked once per block, not once per ID. The hard parts are giving every machine a different machine ID, surviving a clock that jumps backwards, and handling more than 4,096 requests in one millisecond.
Where it shows up
This is a classic system design question. It is asked as 'design a unique ID generator', 'design a distributed sequence', 'how would you generate IDs across shards' or 'design Twitter Snowflake'. It is common at companies that shard their databases, such as social networks, chat apps, marketplaces and payment companies. It also appears inside bigger questions: the URL shortener, a chat system, a news feed and an order system all need IDs, and interviewers often stop to ask how you would make them.
Spec sheeta unique ID generator
worked through below, with the maths
The hard parts of this design are taught step by step in the System Design course: Design a URL Shortener, Database Indexing and B-Trees.
Design a URL shortening service like Bitly from scratch - hashing, storage, redirection, and analytics at scale.
The planner stopped using an index somewhere between 19.7 and 39.8 percent of the table. A query on the second column of a composite index took 37.269 ms against 0.054, and five indexes took the same inserts from 160 ms to 751.
Ten million rows sat in three levels and a hundred rows in one. The same million keys took 21.4 MB inserted in order and 29.6 inserted at random, and after churn the index was 21.92 percent full.
Splitting a database across multiple servers, the nuclear option for scaling writes, and the architecture behind Instagram, Uber, and YouTube.
all part of
System Design Masterclass
770 lessons · about 283 hours · 18 free to read
₹499in India, by UPI
$49everywhere else, by PayPal
You own this course
Continue with Design a URL Shortenerpay once,
yours for life
Show your math. Pulling numbers from thin air signals you have not thought about the load.
Peak ID rate
about 11,600 IDs a second on average, plan for 58,000 at peak
Interview assumption: 1 billion new records a day across all tables (posts, likes, messages, orders). 1,000,000,000 / 86,400 seconds = 11,574 a second on average. Assume the busiest hour runs 5 times the average: 11,574 x 5 = 57,870, so plan for about 58,000 IDs a second.
What one Snowflake machine can make
4,096,000 IDs a second
12 sequence bits give 2^12 = 4,096 IDs in each millisecond. 4,096 x 1,000 ms = 4,096,000 a second on one machine. So one machine could carry the whole 58,000 a second peak about 70 times. We still run the generator on many machines, but for availability and to avoid a network call, not for speed. Twitter's README promised at least 10,000 IDs a second per process, far below this ceiling.
How many machines can make IDs at once
1,024
10 machine bits give 2^10 = 1,024 different machine IDs. If every app server runs its own generator, the fleet can never go above 1,024 running generators at the same moment. With autoscaling (adding and removing servers automatically as traffic changes) and restarts, machine IDs must be returned and reused, which is why they are leased (see the deep dive on machine IDs).
How long the time bits last
about 69.7 years from the epoch
41 bits count up to 2^41 = 2,199,023,255,552 milliseconds. Divide by 1,000 (seconds), 86,400 (days) and 365.25 (years): about 69.7 years. Pick the epoch close to launch day, because every year between 1970 and the epoch is wasted. With an epoch of 1 January 2026 the bits run out in September 2095. Twitter's epoch is 4 November 2010, so its IDs run out in July 2080.
Key size: 64-bit Snowflake vs 128-bit UUID
about 2.9 TB vs 5.8 TB a year, for the key column alone
At 1 billion records a day, a year is 365 billion records. A 64-bit ID is 8 bytes: 365,000,000,000 x 8 = 2.92 TB. A 128-bit UUID is 16 bytes: 5.84 TB. That cost is paid again in every index and every other table that stores the ID, for example as a foreign key (a column that points at a row in another table).
Chance that two random UUIDv4s collide in a year
about 1 in 80 trillion
A UUIDv4 has 122 random bits (RFC 9562). With n random IDs, the chance that any two are equal is about n^2 / 2^123 (the birthday rule). For n = 365 billion: n^2 = 1.33 x 10^23, and 2^123 = 1.06 x 10^37, so the chance is about 1.25 x 10^-14, or 1 in 80 trillion. Random UUIDs are safe from collisions. Their problem is size and index order, not duplicates.
Segment size for a range allocator
about 35 million IDs per segment, one database write per 10 minutes
Meituan's Leaf article recommends a segment (a block of IDs handed out at once) of 600 times the peak IDs per second, which is 10 minutes of IDs. At 58,000 a second: 58,000 x 600 = 34,800,000 IDs per segment. At peak the database is asked for a new segment about once every 10 minutes, and less often per server when several servers share the traffic. Meituan says Leaf can keep issuing IDs for 10 to 20 minutes if the database goes down.
The recommended design runs the generator as a small library inside every app server, not as a separate service. Draw four parts. First, the app servers, here Kubernetes pods. Kubernetes is a system that runs many copies of an app, and a pod is one running copy. Each holds a generator object with three numbers in memory: its machine ID, the last millisecond it used, and a sequence counter. When code needs an ID, it calls the generator. The generator reads the local clock and builds the ID from the time, the machine ID and the counter. There is no network call, so an ID takes microseconds. Second, a coordination service, such as etcd or ZooKeeper. A coordination service is a small, very reliable database that a cluster uses to agree on shared facts. Each server talks to it once at startup to lease a machine ID that no other running server holds. A lease is a claim that expires unless the holder keeps renewing it. Third, time. Every machine runs NTP, the Network Time Protocol, which keeps a machine's clock close to true time by asking time servers. The generator depends on the clock, so clock health is part of the design. Fourth, the databases, here PostgreSQL and MySQL shards (a shard is one of the databases that together hold the data). They store the ID in a BIGINT primary key column. Because new IDs are bigger than old ones, new rows go to the right-hand end of each index. An alternative design runs the generator as its own service with a few replicas behind a load balancer. That is useful when many languages need IDs, or when you want few machine IDs in use. It adds a network call to every ID (Twitter's README quoted a 2 ms response time plus network time), and the service must be as reliable as the databases.
In a real interview, sketch this on the whiteboard before diving into any single box.
Follow pod ids-0 as it starts, then handles one 'create post' request. This is a good order to explain it in an interview.
At startup the pod asks etcd to create the key /id-machines/0 with a lease of, say, 10 seconds, but only if the key does not exist yet. etcd does this in one step that cannot be split, called a compare-and-swap: it writes the key only if the key is still empty. If key 0 is taken, the pod tries the next number. The pod now owns machine ID 0 and renews the lease every few seconds.
Before it serves traffic, the pod checks that its clock is not behind the last time it, or any earlier holder of machine ID 0, used. If the clock is behind, it waits or refuses to start.
A user creates a post. The app code calls next_id() on the local generator object. No network call happens from here on.
The generator reads the current time in milliseconds, for example 1,000 ms after its last call.
The time is newer than the last one used, so the sequence resets to 0. If it were the same millisecond, the sequence would go up by 1. If that made it reach 4,096, the generator would wait for the next millisecond.
id = (now - epoch) << 22 | machine_id << 12 | sequence. The << sign means shift left: move the bits that many places to make room. The | sign joins the three parts into one 64-bit number.
The app inserts the post with this ID as the primary key. The database does not have to make an ID, so the insert can go to any shard.
The API sends the ID as a string, not a number. Discord's API docs always send IDs as strings 'to prevent integer overflows in some languages'. JavaScript is the common case: its largest exact whole number is 2^53 - 1, and a 64-bit ID can be bigger, so a browser would round it.
Walk through each service. The interviewer wants to hear what each one owns, not just the names.
A few dozen lines in each app server. It keeps the machine ID, the last millisecond used and the sequence. A lock makes sure two threads in one process never take the same sequence number. It reads the clock, handles the same-millisecond and clock-went-back cases, and returns a 64-bit number.
Hands each running generator a machine ID that no other running generator holds. In etcd this is a key per machine ID, attached to a lease; etcd deletes every key attached to a lease when the lease expires. In ZooKeeper it is an ephemeral node, which ZooKeeper deletes when the session that created it ends. Twitter chose worker numbers through ZooKeeper at startup.
Each machine's clock, kept close to true time by NTP. The generator trusts the clock only to move forward. NTP should be set up to slew the clock (speed it up or slow it down a little) rather than step it (jump it to a new value), so it never jumps backwards in normal running.
A small record, saved every few seconds per machine ID, of the latest millisecond used. A process that restarts reads it, so a restart after a clock change cannot reuse old milliseconds. Meituan's Leaf writes this time to ZooKeeper every 3 seconds and checks it at startup.
A BIGINT column with no auto-increment. The app supplies the ID. Because the time comes first in the number, new rows go to the end of the index. Most databases store an index as a B-tree, a tree of pages kept in order, and its end is the cheapest place to insert.
Counts of clock-went-back events and their size, sequence overflows (calls that had to wait for the next millisecond), lease losses, and the gap between each machine's clock and NTP. Any one of these going up is an early warning of a duplicate.
machine ID lease (etcd key). Created with a compare-and-swap that only succeeds if the key does not exist. If the pod dies, the lease stops being renewed and the key is deleted when the TTL runs…
Every table for a unique ID generator, its keys, and which store fits it and why.
The options side by side. There are six families of answer, and an interviewer expects you to know them all before picking one. One: a single database's auto-increment. The database keeps a…
9 deep dives on the parts that break at scale, with 3 diagrams: The options side by side; The Snowflake bit layout and the arithmetic; Assigning machine IDs without duplicates.
Library inside each app server vs a separate ID service. A library has no network call and no extra service to run, but every app server needs a machine ID, which uses up the 1,024 slots fast with autoscaling. A separate…
7 decisions an interviewer expects you to defend, each with the alternative and why it loses here.
Two servers came up with the same machine ID after an autoscaling event. What breaks, and how do you stop it?
5 follow-up questions with model answers, the interview scorecard for this question, and a mock interview on Design a unique ID generator with the AI tutor.
Twitter announced Snowflake in June 2010 because its move to Cassandra and sharded MySQL left it with no way to make unique IDs; the code splits the 10 machine bits into 5 datacenter and 5 worker bits and refuses to make IDs when the clock moves back. Instagram built the same idea inside PostgreSQL with a PL/pgSQL function per logical shard: 41 bits of time, 13 bits of shard ID and 10 bits of sequence. Flickr's 2010 post describes two MySQL ticket servers, one odd and one even, in production since January 2006. Discord uses 42-bit timestamps from a 2015 epoch and sends IDs as strings. MongoDB's ObjectId puts 4 bytes of seconds first. Sony's Sonyflake uses 10 ms ticks to last 174 years. Meituan's Leaf offers both a segment mode and a Snowflake mode with ZooKeeper-assigned workers. RFC 9562 standardised UUIDv7 in 2024, and PostgreSQL 18 ships uuidv7().
Sources
If any of these topics are fuzzy, the interviewer will catch it. Each lesson is 15 to 60 minutes with diagrams, code, and a quiz.
Design a URL Shortener
capstone / capstone
Database Indexing
foundation / database fundamentals
B-Trees
foundation / database fundamentals
Database Sharding
foundation / database fundamentals
Consistent Hashing
intermediate / data replication distribution
StatefulSets
intermediate / kubernetes containers
NewSQL Databases
intermediate / database types storage
Leader Election
advanced / distributed systems core
Distributed Locks
advanced / distributed systems core
Lamport Timestamps
advanced / distributed systems core
Vector Clocks
advanced / distributed systems core
interview readiness
Three questions from this guide. Answer them without scrolling up, the way you would have to in the room.
India: UPI, cards or netbanking through Razorpay. Elsewhere: card or PayPal. Download at once from My packs.
Free PDF · 79 pages
25 real tech interview questions, answered in full
Five from each of our AI, GenAI, Inference, Maths for ML and Forward Deployed packs. Each with a diagram and a model answer. Free by email.
The concepts were explained in a clear and structured way, with practical examples that made even complex system design topics easier to understand. I especially liked the focus on real-world architecture, scalability, trade-offs. The content was well designed, engaging, and highly useful for anyone looking to strengthen their system design skills. Highly recommended for software engineers preparing for system design interviews or wanting to build a stronger foundation in designing scalable systems.