System design sample solution

System design: design product recommendations

A step-by-step system design answer you could actually give in 60 minutes.

System design interview · Sample 60-minute answer · Not Amazon's actual design · Independent, not affiliated with Amazon

The system design question

Design the 'customers who bought this also bought' and 'recommended for you' sections. They should reflect recent activity and load quickly on every product page.

Agree on the scope (5 minutes)

Say up front what you're covering.

We'll designWe'll skip
'Also bought' lists for each productThe details of the machine learning model
'Recommended for you' lists for each shopperThe product page itself
Mixing in recent activityAds and sponsored items
Serving both fast on page loadEmail recommendations

Then agree on what "good" means:

  • Fast: adds less than about 50 ms to a product page.
  • Recent: what you viewed a minute ago should change what you're shown.
  • Always shows something: if anything fails, show popular items instead of an empty box.
  • Good enough: we'll measure quality by clicks and purchases, not get it perfect up front.

Rough numbers (5 minutes)

Assumptions, but reasonable: 300 million shoppers, 500 million products, 5 billion product page views a day, 50 million orders a day, and we keep the top 50 recommendations per product and 100 per shopper.

~60K
product page views per second
~300 GB
of 'also bought' lists
~360 GB
of 'for you' lists
50M
orders a day to learn from
QuestionRough mathWhat it means
How many lookups?5 billion views ÷ 86,400, and two lists per pageAbout 120K lookups a second, so each one has to be a simple read
How big are 'also bought' lists?500 million products × 50 × about 12 bytesAbout 300 GB. Fits in a split-up key-value store
How big are 'for you' lists?300 million shoppers × 100 × about 12 bytesAbout 360 GB, similar
Can we compute it live?Comparing a shopper against millions of others per page viewNo. The heavy work has to happen ahead of time

The overall design (10 minutes)

Shopper activityviews and ordersEvent streamevery actionBatch and stream jobsbuild listsRecommendation storeready-made listsRec serviceread and adjust
Background jobs build the lists ahead of time. The page just reads one and adjusts it.
  1. Every view, add to cart and order goes onto an event stream.
  2. A nightly batch job reads months of orders and builds an 'also bought' list for every product and a 'for you' list for every shopper. It saves them in a key-value store.
  3. A streaming job reads the same events as they happen and keeps each shopper's last few dozen actions, plus fresh co-purchase counts for new or trending products.
  4. When a product page loads, the rec service reads the saved lists, adjusts them with recent activity, removes things you already bought, and returns about 20 product IDs.
  5. The page fetches product details for those IDs from the catalog cache.

What the apps need to do

ActionWho does itWhat's sent
Also bought for a productProduct pageProduct ID and how many items
Recommended for a shopperProduct and home pagesShopper ID, the page they're on and how many items
Record activitySite and appsShopper ID, product ID, action type and time

What we store and where

DataWhere it goesWhy
Activity eventsEvent stream, then cheap long-term storageRaw input for every job
'Also bought' listsKey-value store, split by product IDOne read per page load
'For you' listsKey-value store, split by shopper IDOne read per page load
Recent activityIn-memory store, per shopperLast few dozen actions, kept for a day or so
Popular items by categoryCacheFallback for new shoppers and failures

Step 1: Building 'also bought' lists (10 minutes)

The basic idea: for every order, every pair of products in it gets a point. Also count pairs bought by the same shopper within a few weeks, since lots of related things aren't in the same order. After a pass over a few months of orders, product A's list is the products with the most points next to A.

Raw counts favor things everyone buys, like batteries. So divide by how popular each product is overall. That turns 'often bought with A' into 'bought with A much more than you'd expect'.

Counting every pair is a big job, so it runs as a nightly batch across many machines, split by product. Huge orders, like someone buying 200 things for an office, would make tens of thousands of pairs, so cap how many items per order we count.

The result goes into a key-value store split by product ID, like any other sharding setup. Swap in the new lists all at once so pages never see half old, half new.

Step 2: Building 'recommended for you' (12 minutes)

This one works in two steps. First gather a few hundred candidates: 'also bought' items for things you bought or viewed, popular items in categories you browse, and items similar shoppers bought. Then score each candidate and keep the best 100.

Scoring is where a machine learning model goes. It takes things like how you've reacted to similar items, price range and how recently you looked at the category, and predicts how likely you are to click or buy. We said we'd skip the model's details, so treat it as a box that returns a score.

This also runs nightly for every active shopper. Shoppers who haven't visited in months don't get a list. If they come back, they get popular items until the next run.

Why not compute it on page load?

Gathering candidates means dozens of reads, and scoring hundreds of items takes time. Doing that 60K times a second would be slow and expensive. Precomputing means a page load is one read. The cost is staleness, which the next section fixes.

Step 3: Reacting to recent activity (8 minutes)

A nightly list doesn't know you started shopping for a tent ten minutes ago. So a stream processing job keeps your last few dozen actions in memory, updated within seconds.

At page load, the rec service reads your nightly list, then mixes in the 'also bought' items for what you just viewed and drops anything you just bought. That's a few extra reads from fast stores, still well under our 50 ms. It's a small, quick adjustment, not a full rerun.

The same streaming job keeps short-term co-purchase counts for the last day or so. That helps brand-new products and sudden trends show up before the nightly job sees them.

All the lists are read through a cache, since popular products get the same 'also bought' list requested thousands of times a second.

Choices you should be able to defend

We choseInstead ofBecauseWe'd reconsider if
Precomputed lists, adjusted at page loadComputing everything livePage loads stay fast and cheapWe had few products and shoppers
Nightly batch plus a light streaming layerEverything in streamingBatch is simpler and easier to rerun when there's a bugFreshness mattered more than cost and simplicity
Popularity-adjusted countsRaw co-purchase countsStops every list being full of batteriesNever, raw counts are almost always worse
Lists for active shoppers onlyLists for everyoneSaves storage and compute on people who aren't visitingInactive shoppers came back often enough to notice

What could go wrong (5 minutes)

What happensWhat we do about it
The nightly job failsKeep serving yesterday's lists. They're a day staler but still decent
The rec service is slowThe page gives up after 50 ms and shows popular items, or hides the section
The streaming job falls behindRecent activity is late, so recommendations act like the nightly ones until it catches up
A bad model shipsWatch click rates per version and switch back to the previous lists
A new product has no dataFill its list from similar products in the same category until it has orders

Follow-up questions (5 minutes)

How do you know it's working?

Run A/B tests: show a slice of shoppers the new version and compare clicks and purchases.

How do you avoid showing the same items everywhere?

Track what's been shown on this visit and push repeats down the list.

What about a shopper with no history?

Start with popular items in the category they're looking at, and use their first few clicks right away through the streaming layer.

How the 60 minutes add up

MinutesWhat you're doing
0–5Agree on what you're building
5–10Rough numbers
10–20Draw the overall design
20–30Building 'also bought' lists
30–42Building 'recommended for you'
42–50Reacting to recent activity
50–55What could go wrong
55–60Follow-up questions

Key concepts used here

Further reading

We wrote this sample answer ourselves.

Practice Loop is independent and isn't affiliated with or endorsed by Amazon.