Section 2: Two Clocks, One Contract - Requirements (Functional & Non-Functional)
Executive Summary: This section turns Section 1's clarifications into a contract ClipKart could sign. We write six functional requirements (the Top-10 button, every product's rank in every category, per-category best-seller lists, the counting rules, serve-time eligibility, and a refusal to expose raw sales), name what is out of scope and why, and attach numbers to every quality: Top-10 freshness of 2 minutes at p99 against rank freshness of 75 minutes worst case, 50 ms and 10 ms latency targets, 99.99% read availability, exact counts and unique ranks. The section's real lesson is that the two features run on two different clocks, and writing that down now is what makes the two-pipeline architecture later look inevitable rather than clever.
The clarifications are done, and the interviewer leans back: "Good. So what exactly are we promising?" This is where many candidates go soft. "The Top-10 should be real-time-ish, ranks should be accurate, and it should scale" is three adjectives, not a contract. You can't test an adjective, and you can't page anyone when one is violated. A Staff candidate writes requirements that an on-call engineer could turn straight into alerts. Here that matters more than usual, because the requirements for the button and for the badge pull in opposite directions, and the gap between them is the whole design.
The Functional Contract
Six requirements, each phrased so you could write an acceptance test for it:
- FR1, the Top-10 button. For any scope in {overall, each of the 30 top-level departments} and any window in {1h, 4h, 24h}, return the 10 products with the most counted units in that trailing window. That is 31 scopes × 3 windows = 93 lists, and nothing else. The windows slide at 1-minute granularity and are measured in event time, meaning the moment payment was confirmed.
- FR2, every product's rank. For any product sold at least once in the trailing 30 days (the ranked set, 40M products), return its rank overall and in every category it belongs to, where a category's rank covers its whole subtree. Priya's StrikeGuard Pro helmet (P-88412) is mapped to Protective Gear and Head Protection, but it must also hold a rank in Cricket, Sports Equipment and Safety. That gives it five memberships and three numbers worth showing at the 20:00 snapshot: #1,056 overall, #13 in Sports Equipment, #24 in Safety.
- FR3, best-seller lists. For each of the 20,000 categories, plus overall, publish the top 100 in rank order. These are the category best-seller pages.
- FR4, counting rules. Count units on payment-confirmed order lines. A cancellation retracts from the minute of the original order, not the minute it was cancelled. Each buyer contributes at most 5 units per product per 24 hours. Orders the fraud service flags are retracted the same way cancellations are.
- FR5, serve-time eligibility. Never show an out-of-stock, delisted or restricted product in a Top-10 list, even if it earned the spot. The filter runs when the list is served, not when it is computed, because stock changes faster than any list.
- FR6, no raw counts. The public surface exposes ranks, never unit counts. Sales velocity is competitive intelligence, and a public number gets scraped hourly by every rival seller.
FR4 deserves a moment, because it is where "most bought" stops being vague. Counting orders would undercount multipacks. Counting distinct buyers would undercount honest bulk purchases. Counting units with no cap lets one buyer with 500 crowbars crown a product. Units with a per-buyer cap is the reading that is both fair and hard to game.
Key Insight: FR2 and FR3 are a different kind of requirement from FR1. FR1 asks for the head of 93 lists. FR2 asks for the full order of 20,000 categories, because you can't say "#1,056" without knowing the 1,055 products above it. Read side by side, the functional list already shows that one mechanism will struggle to serve both.
Out of scope, with reasons
What you leave out is scored as closely as what you include, and the reasons are where the points are:
| Excluded from v1 | Why | Where it comes back |
|---|---|---|
| Personalized Top-10 | Breaks the "93 shared lists" property that makes the button CDN-cacheable | Section 11, as per-segment lists |
| Per-city lists | A new scope dimension, so more lists, but no new mechanism | Sections 9 and 11 |
| Netting out returns | Returns arrive days later, when a week-old sale's decayed weight is already about 1/128 of its original | Section 11, if buy-then-return gaming shows up or a high-return category (fashion, around 30%) needs it |
| Arbitrary N ("last 7 hours") | Would turn 93 precomputed lists into an ad-hoc range query on every click | Section 9, through a minute-bucket OLAP store |
| Multiple marketplaces | One country, one marketplace, as agreed | Section 11: one pipeline per marketplace, not a global one |
Quick check before moving on:
Sign in to continue reading
The rest of this lesson is available with a free account. Signing in with Google or Microsoft is free.
Sign in to read the full lesson