Study 01 · data pipeline
Pushing tonight's prices to every booking channel
A host with 400 listings changes a rule. Every night the engine recalculates ~365 days × 400 listings and has to land those prices on Airbnb, Booking.com and Vrbo, each with its own rate limits and quirks.
Requirements
- Functional: recalculate on rule change and nightly; push changed dates only; show per-listing sync status.
- Non-functional: prices live within minutes of a change; no lost updates; respect channel rate limits; a failure on one channel never blocks the others.
- Scale (assumed): ~150 M date-prices a night, bursts after a big customer edits a group.
Key decisions
- Diff, don't resend: store the last pushed price; only changed dates enter the queue.
- One queue per channel with its own workers and backoff, so Vrbo throttling doesn't slow Airbnb.
- Idempotent jobs keyed by listing + date range: retries can't double-apply.
- Dead-letter queue for hard failures, surfaced to the host instead of retried forever.
Rule change / nightly cron→Pricing engine→Diff vs last pushed→Channel queues→Channel adapters (rate-limited)→Airbnb · Booking · Vrbo↺Sync status store
What it changes in the interface
- Sync is not one state. A listing can be queued, syncing, synced, partially failed, or paused; the calendar shows which dates are live.
- "Synced 2 min ago" beats a spinner: the timestamp answers "can I trust this price?"
- Failures name the channel and the fix ("Reconnect Vrbo"), because the system already knows which queue failed.
Study 02 · event system
Alerts that deserve attention
Hundreds of things can go wrong in a portfolio: a missing base price, a paused sync, blocked dates, a competitor price drop. Sending every one of them trains users to ignore all of them.
Requirements
- Functional: detect issues, rank them, group duplicates, deliver in-app, by email or push based on preference; let users snooze or switch off types.
- Non-functional: critical alerts within minutes; never the same alert twice; quiet by default.
Key decisions
- Event stream → rules engine: detectors emit events; rules decide severity from revenue at risk, not from the event type alone.
- Dedupe window per listing + issue, and roll-ups ("12 listings have stale syncs") instead of 12 alerts.
- Preferences are data the engine reads, so "switch this off" takes effect immediately.
- Critical alerts bypass preferences; everything else respects them.
Detectors (sync, pricing, calendar)→Event stream→Rules: severity · dedupe · roll-up→Preferences→In-app · email · push
What it changes in the interface
- Each alert carries its one fixing action, because the rule that raised it knows the cause.
- Severity is shown as revenue at risk, which explains the order of the list.
- A "Manage alerts" sheet maps one-to-one to the preference data the engine reads.
Study 03 · query layer
Custom reports on big portfolios
Large customers want their own metrics, formats and targets across thousands of listings and years of bookings, and they expect the table to feel instant.
Requirements
- Functional: pick metrics (including formulas), group by listing, market or tag, compare to targets, schedule exports.
- Non-functional: common views under ~1 s; heavy ones allowed to take longer but never block the UI; numbers match the dashboards exactly.
Key decisions
- A metric catalogue: one definition per metric, used by reports and dashboards alike, so numbers always agree.
- Pre-aggregated daily tables per listing; reports roll those up instead of scanning raw bookings.
- Cache by query shape, invalidated when the day's data lands.
- Async jobs for exports and huge ranges, with progress and a notification.
Bookings · prices · calendars→Nightly aggregation→Metric catalogue→Query service + cache→Report builder UI→Scheduled exports
What it changes in the interface
- Formula builders validate against the metric catalogue as you type, not after you run the report.
- "Data as of 6:00 today" is honest about the nightly aggregation.
- Big queries show progress and can finish in the background; the user is never stuck staring at a frozen table.
Method
How I approach an HLD round
- Clarify the job and the scale. Who uses it, how often, how much data, what must never go wrong.
- Functional, then non-functional requirements. Latency, consistency, availability: say which one wins when they conflict.
- Draw the boxes. Clients, API, services, queues, stores, caches, third parties. Name the data on each arrow.
- Walk one request end to end, then the failure of each box.
- Scale it: where's the bottleneck at 10×? Partition, cache, queue, or pre-compute.
- Bring it back to the user: which states and messages the design needs because of these trade-offs.
Case study I learn from · Slack · by J.V. Kaushik
Making Slack’s AI something students can trust
Students already used the AI inside Slack, but nothing told them what it did with their conversations. Most wanted its help; almost none trusted it. Over 16 weeks the team designed transparency into the moments the AI acts.
How they worked
- Worst cases first: “Black Mirror” sessions surfaced realistic failures, such as a history discussion flagged as hostile, or a catch-up summary that took a joke as a conflict.
- Wizard of Oz testing: without access to Slack AI, a person played the AI live for 40 students, so their reactions were real.
- Proof from their own chat: the same banter read with and without context showed that context changes what the AI understands.
What survived
- Cut: alerts whenever someone typed personal details. Testers said it fired on everything.
- Evolved: an emoji “seriousness” slider was too ambiguous and became a plain Engagement Style dropdown.
- Shipped: an inline note on what the AI just did, why, and which data it used. It became part of all 3 final features.
What I take from it
- Explain the AI at the moment it acts, not in a settings page. It’s the same instinct as showing the reasoning in Base Price Help.
- If you can’t build the AI yet, fake it convincingly and test the trust, not the model.
Summary in my words. Read the full case study by J.V. Kaushik ↗
Case study I learn from · Cleartrip · by Shushant Kumar
Redesigning international flight search
Long-haul search had inherited the domestic interface and lost people at the moment they compared options: pricing felt opaque, waits were long and travellers feared overpaying. The redesign shipped in June 2023 with +200% booking value and +23% transactions.
The calls that mattered
- Start where the funnel leaks most. Only 17.4% moved from results to an itinerary, so the result card came before the search form.
- Subtract. The flight data offered dozens of fields; a short primary list stayed on the card and the rest moved to the expanded view.
What changed
- Departure and arrival side by side, labels next to icons, and the final price after coupons.
- Sort cut to the two ways people think: fastest and cheapest. Stops, airlines and times were promoted as filters.
- Details open in a side sheet, so you never leave the comparison, with cancellation and date-change rules upfront.
What I take from it
- Pick the funnel step with data before picking the screen everyone has opinions about.
- Defend a short card in the room. It’s the same fight as merging three price suggestions into one.
Summary in my words. Read the full case study by Shushant Kumar ↗