The problem
"Design Pinterest." People save images onto boards, such as "Party ideas", often saving a pin someone else saved first, and they scroll a home feed of pins chosen for their interests. They also search: "chocolate cake".
This practice problem reuses the pattern of Design Instagram. Four things are new: one image saved onto thousands of boards, a feed picked for each person rather than built only from follows, a grid that shows many pins of different heights at once, and search over the pins' descriptions. Park messages and shopping: each is a design of its own.
The numbers
From the interviewer: 100 million daily users, each opening the home feed about 10 times a day. Round a day to 100,000 seconds (86,400 really); busy hours run about 5× the average.
- Feed opens: 100 million × 10 = 1 billion a day, 10,000 a second on average (about 11,600 with 86,400), so about 50,000 a second at busy hours.
- Saves: say 300 million a day, but only 10 million new images: about 30 saves per image on average, and a popular image far more.
- Storage: 300 million pin rows of about 500 bytes is 150 GB a day; the 10 million new images at about 1 MB each are 10 TB a day.
Pins and boards: each image once
image id, keys of its sizes, width, height, save_count
board id, owner_id, name
pin id, user_id, board_id, image_id, description, time
A cake photo saved by 10,000 people is one image and 10,000 pins. Images and boards are many-to-many, and the pin is the join table from Data Modeling: who saved which image onto which board, with their own description. Saving is POST /pins with the image, the board and the description. The 10,000 pin rows take about 5 MB, while the photo and its sizes are stored once.
Copying the photo with each save would cost 10 GB for one picture, 2,000 times the pin rows, and give the CDN 10,000 addresses to cache for the same bytes. A list of savers inside the image's row fails too: a popular row would grow and be rewritten with every save. The image keeps a save_count, a deliberate copy of what its pins already say, because search ranks by it.
The home feed: ranked ahead of time
The interviewer wants most of the home feed picked for each person's interests. Say ranking one person's feed from scratch means scoring about 1 million pins: at 50,000 opens a second that is 50 billion scores a second, on the busy path. Pushing each new pin to everyone interested in its topic, the way Twitter pushes tweets to followers, doesn't fit either: a broad interest covers a huge share of users, and interests shift with every click.
Instead a batch job runs each night, ranks pins for each person from what they saved and clicked, and stores a candidate list of pin ids. Opening the feed is one read of that list, like Twitter's timeline cache. Say 500 ids a person: 100 million × 500 × 8 bytes = 400 GB, a few cache servers. At read time a light pass mixes in new pins from boards the person follows and drops pins they've seen, so the feed still moves during the day.
The grid: thumbnails, loaded as you scroll
The home screen is a masonry grid: 3 columns about 240 px wide, each pin as tall as its image. A phone shows about 6 pins at once, and a page of the feed brings 50. Two choices keep it fast:
- The size that fits a column. Say a 240 px thumbnail is about 30 KB: 6 tiles cost 180 KB. The 1 MB originals would cost 6 MB and look no sharper in a 240 px column.
- Lazy loading. The app fetches each image just before it scrolls into view. Loading all 50 thumbnails at once is 1.5 MB, and the 6 on screen would wait behind 44 the user hasn't reached.
The feed answer carries each image's width and height, so the app lays out the columns before the pictures arrive and tiles don't jump as they load.
Search: one entry per image
Search works as in Search Engine: an inverted index maps each word to a sorted list of ids. The question is which ids, since the words come from pins and one image has many pins. Take four: p1, p2 and p4 save image 77 ("chocolate cake", "birthday cake", "easy chocolate cake"), and p3 saves image 12 ("cake pops"). Indexed by image:
word images
birthday 77
cake 12, 77
chocolate 77
easy 77
pops 12
Indexing images, not pins, means a search finds each photo once, by words any of its savers used. Indexing pins would return image 77 once per save, so the first pages could be one photo again and again. With no index at all, every search would scan billions of pin rows. The save_count is a strong ranking signal: an image many people saved is usually a good result.
Same pattern as Instagram
Everything about images carries over. A new image goes straight to object storage with a signed upload URL, workers make its sizes off a queue, and a CDN sends the thumbnails from edges near the viewers. Saving an existing pin adds only a row: no bytes move at all.
Summary
- Scope: save pins onto boards, a feed picked for you, a grid, search.
- Data: each image once; a pin row per save, the join table.
- API:
POST /pins,GET /home?cursor=…,GET /search?q=…. - Numbers: about 50,000 feed opens a second at busy hours; 400 GB of candidate lists.
- Services: a nightly batch job writes each person's candidates; the feed reads them.
- Grid: 240 px thumbnails, loaded as they near the screen.
- Search: an index from words to images, ranked by saves.