Section 2: Promises Over Someone Else's Data - Requirements (Functional & Non-Functional)
Executive Summary: This section turns Section 1's answers into a contract. We number the functional requirements so every later section can point at them, draw the out-of-scope line with a reason for each exclusion, and then set the non-functional dials per path rather than for "the service": a hot forward read, an expensive tag page, and an asynchronous bulk lane, each with its own latency and availability target. We state the consistency model as five explicit promises, write the abuse limits down before anyone asks, and defend the two choices interviewers push on hardest: counts that are an honest lower bound instead of exact, and an extra nine for reads that we refuse to give writes.
The clarifications are done, and the interviewer caps the marker: "Good. So what exactly are we committing to?" This is where most candidates write "users can tag things, it should be fast and secure" and move on. That sentence can't be tested, and it hides the one thing Section 1 uncovered: every requirement here has to hold over content and permissions that three other systems own. So each requirement below is something a test could check, and each number is one an on-call engineer could be paged on.
The Functional Contract
Strip the prompt to its verbs and you get nine. Numbering them is not bureaucracy; it lets Section 4's endpoints and Section 5's tables trace back to a promise.
| # | Requirement | What it really commits us to |
|---|---|---|
| FR1 | Add or remove a tag on any item (Jira issue, Confluence page, Bitbucket pull request, or an Azure DevOps work item) | Only someone who can edit the item may tag it, and the owning product decides that. Adding a tag that doesn't exist yet creates it. Repeating an add is harmless. |
| FR2 | Batch-get the tags of many items | One call renders a whole board or search result page, up to 200 items at a time. |
| FR3 | The tag page: everything carrying a tag, across products | Permission-trimmed, paginated 25 at a time, filterable by product. It never reveals that an item you can't see exists. |
| FR4 | Autocomplete as you type | From a 2-character prefix, return 10 suggestions drawn only from vocabulary you could already see. |
| FR5 | Popular-tags panel | Per container (a project, space or repo), or per tenant for open tenants where every member sees every container. |
| FR6 | Admin rename | Synchronous for the admin. The new name shows immediately for the admin, within seconds everywhere. |
| FR7 | Admin merge and delete | Asynchronous: the request returns a job, and the tag disappears from view immediately while the cleanup runs. |
| FR8 | Bulk tag | Up to 1,000 items per request, on a separate lane. |
| FR9 | Events out | Every change is published so product search indexes, activity streams and automation can follow along. |
Walk Dana through it and the list earns its keep. At 14:05 Dana tags PAY-4312, the postmortem page, PR 881 and the restricted PAY-4315 with checkout-outage (FR1). The PAY board re-renders with the tag on the card (FR2). Priya clicks the tag and sees three items; Sam clicks it and sees two (FR3). That last sentence is a functional requirement, not a security footnote. It is the reason FR3 is the hardest line in the table.
Key Insight: FR3, FR4 and FR5 are three different questions over one fact. "Which items carry this tag?", "which tags start with ch?" and "which tags are popular here?" can each leak what the user isn't allowed to see. Writing all three down together is how you signal that the permission problem isn't confined to the tag page.
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