System Design MCQs multiple-choice questions with answers & explanations
All 34 System Design quiz questions on one page. Pick an answer in your head, then open Show answer to check it and read why. Want a score and a timer? Take them as a quiz instead.
- 1.mid
A search-as-you-type box sometimes shows results for 'rea' after the user has finished typing 'react', because the older request resolved last. What fixes this?
- AIncrease the debounce delay so requests can never overlap
- BCache responses in memory, keyed by the query string
- CAbort the previous request, or ignore responses that don't match the latest query
- DShow a loading spinner until every request has finished
Show answer
Answer: C (Abort the previous request, or ignore responses that don't match the latest query)
Debouncing reduces how many requests you send, but any two in-flight requests can still resolve out of order. Cancel the previous one (
AbortController, or RxJSswitchMap) or check that a response matches the latest query before rendering it. A cache makes repeat queries faster but doesn't fix ordering. - 2.easy
For an autocomplete input, you want to call the API only once the user has paused typing for 300 ms. Which technique is that?
- AThrottling
- BDebouncing
- CMemoization
- DRequest batching
Show answer
Answer: B (Debouncing)
A debounce waits until events stop arriving for the given time and then fires once, which suits search inputs. A throttle fires at most once per interval while events keep coming, which suits scroll and resize handlers.
- 3.hard
In an autocomplete, keyboard focus stays in the text input while the user arrows through the suggestions. Which ARIA attribute tells assistive technology which option is highlighted?
- A
aria-activedescendanton the input, set to the id of the highlighted option - B
aria-selected="true"on the input while an option is highlighted - C
aria-live="assertive"on the listbox so changes are announced - D
tabindex="0"on every option so each one can take focus
Show answer
Answer: A (
aria-activedescendanton the input, set to the id of the highlighted option)In the combobox pattern the input has
role="combobox",aria-expandedandaria-controlspointing to arole="listbox", andaria-activedescendantnames the activerole="option"(which also getsaria-selected="true"). Focus never leaves the input, so the user can keep typing. - A
- 4.easy
Which Core Web Vital measures how quickly a page responds to user interactions?
- ALCP
- BCLS
- CTTFB
- DINP
Show answer
Answer: D (INP)
Interaction to Next Paint (INP) replaced FID as a Core Web Vital in 2024. It looks at the latency of interactions throughout the visit; "good" is 200 ms or less at the 75th percentile. LCP measures loading and CLS visual stability, while TTFB is a diagnostic metric, not a Core Web Vital.
- 5.mid
The LCP element of a landing page is a large hero image. Which change is most likely to make LCP worse?
- AAdding
fetchpriority="high"to the hero image - BAdding
loading="lazy"to the hero image - CServing it as AVIF or WebP at the displayed size
- DPreloading the hero image
Show answer
Answer: B (Adding
loading="lazy"to the hero image)Native lazy loading holds the request back until layout shows the image is near the viewport, which delays the LCP. Lazy-load below-the-fold images only; the LCP image should be discoverable in the initial HTML, prioritized, and correctly sized.
- AAdding
- 6.easy
Images pop in and push the text down as they load, hurting CLS. What's the standard fix?
- ALazy-load every image so they arrive after the text settles
- BConvert the images to SVG so they render instantly
- CInsert the images with JavaScript after the page has rendered
- DSet
widthandheight(or CSSaspect-ratio) so space is reserved early
Show answer
Answer: D (Set
widthandheight(or CSSaspect-ratio) so space is reserved early)With intrinsic dimensions the browser knows the aspect ratio and reserves the box, even with responsive CSS like
width: 100%; height: auto. The same idea applies to ads, embeds and late banners: reserve their space up front. - 7.hard
INP is poor on a product listing: each filter click runs a 300 ms synchronous function that filters 20,000 items and re-renders. Which change most directly improves INP?
- APreload the web fonts so text renders sooner
- BPut a CDN in front of the product API
- CLazy-load the product images below the fold
- DSplit the work into chunks that yield to the main thread, or use a Web Worker
Show answer
Answer: D (Split the work into chunks that yield to the main thread, or use a Web Worker)
INP measures the time from an interaction until the next frame is painted, and a long synchronous task blocks that paint. Yielding between chunks, virtualizing the list, rendering the results as a non-urgent update, or moving work to a worker all shorten the blocking time. The other options affect loading, not interaction latency.
- 8.mid
Which
Cache-Controlheader is best for a fingerprinted bundle likeapp.3f2a1c.js?- A
no-store - B
no-cache - C
public, max-age=31536000, immutable - D
max-age=0, must-revalidate
Show answer
Answer: C (
public, max-age=31536000, immutable)The filename changes whenever the content does, so a given URL never changes and can be cached for a year without revalidation. The HTML that references the bundles should use
no-cache(store it, but revalidate every time) so users pick up new hashes right after a deploy.no-storedisables caching entirely. - A
- 9.hard
A CDN that supports
stale-while-revalidatecaches a response withCache-Control: max-age=60, stale-while-revalidate=300. A request for it arrives 120 seconds later. What happens?- AThe cached response is served with no request to the origin
- BThe cached response is served immediately and the CDN revalidates it with the origin in the background
- CThe request waits for a fresh response from the origin
- DThe cached copy is discarded because it is older than 60 seconds
Show answer
Answer: B (The cached response is served immediately and the CDN revalidates it with the origin in the background)
For the first 60 seconds the response is fresh. Between 60 and 360 seconds (max-age plus the stale-while-revalidate window) it's stale but may be served instantly while the cache refreshes it asynchronously. After that, a blocking request to the origin is required.
- 10.mid
Which of these does NOT protect against CSRF?
- ASetting session cookies with
SameSite=LaxorSameSite=Strict - BRequiring an anti-CSRF token on state-changing requests
- CChecking the
Originheader on the server - DMarking the session cookie
HttpOnly
Show answer
Answer: D (Marking the session cookie
HttpOnly)CSRF works because the browser attaches cookies to the forged request automatically; the attacker never needs to read the cookie.
HttpOnlyonly stops JavaScript from reading it, which limits session theft via XSS but does nothing against CSRF. - ASetting session cookies with
- 11.hard
An attacker manages to inject an inline
<script>into your page. Which Content-Security-Policy blocks it while still allowing your own/static/app.js?- A
script-src 'self' 'unsafe-inline' - B
script-src 'self' - C
default-src 'none' - D
frame-ancestors 'none'
Show answer
Answer: B (
script-src 'self')Without
'unsafe-inline', CSP blocks inline scripts and inline event handlers, and'self'allows scripts from your own origin.default-src 'none'would block your bundle too, andframe-ancestorsonly controls who may embed the page. If you need specific inline scripts, allow them with a nonce or hash. CSP is defense in depth: you still escape output. - A
- 12.easy
Your framework escapes interpolated text automatically. Which of these can still introduce XSS when given a comment written by a user?
- ARendering it with text interpolation such as
{{ comment }} - BAssigning it to
element.innerHTML - CAssigning it to
element.textContent - DCalling
element.setAttribute('title', comment)
Show answer
Answer: B (Assigning it to
element.innerHTML)innerHTMLparses the string as HTML, so a payload like animgtag with anonerrorhandler runs attacker code. The same applies to React'sdangerouslySetInnerHTMLand Angular'sbypassSecurityTrust*APIs. If you must render user HTML, sanitize it with a library such as DOMPurify. - ARendering it with text interpolation such as
- 13.mid
An infinite-scroll feed loads
?page=3&limit=20. New posts are added at the top while the user scrolls, so they see duplicate posts. What is the fix?- ACursor pagination: fetch the items after the last loaded item's id
- BUse smaller pages so fewer items shift between requests
- CRefetch every loaded page each time the user scrolls
- DCache each page in localStorage by its page number
Show answer
Answer: A (Cursor pagination: fetch the items after the last loaded item's id)
With offsets, inserting items at the top shifts every page, so the next page repeats items (and deletions make you skip some). A cursor anchors the next page to a stable position in the ordered list, and it is also cheaper for the database than large offsets.
- 14.easy
What is the recommended way to decide when to load the next page of an infinite-scroll list?
- AA
scrolllistener that callsgetBoundingClientRect()on every event - BPolling
window.scrollYwithsetInterval - CAn
IntersectionObserverwatching a sentinel element near the list end - DLoading all pages up front and revealing them as the user scrolls
Show answer
Answer: C (An
IntersectionObserverwatching a sentinel element near the list end)IntersectionObserver reports visibility changes asynchronously, off the scroll hot path, so it avoids forced layouts on every scroll event. A
rootMarginlike600pxstarts fetching before the user reaches the bottom. Also keep the footer reachable and offer a Load more fallback. - AA
- 15.mid
A feed now renders 10,000 items and scrolling is janky. What most directly helps?
- AWrap every item component in
memoso items don't re-render - BMove the feed data out of memory into IndexedDB
- CAnimate scrolling with CSS transforms instead of native scroll
- DVirtualize the list so only the visible items plus a small buffer exist in the DOM
Show answer
Answer: D (Virtualize the list so only the visible items plus a small buffer exist in the DOM)
DOM size drives style, layout and memory costs, and virtualization keeps a few dozen nodes mounted regardless of list length (react-window, TanStack Virtual, Angular CDK virtual scroll). Trade-offs: variable heights must be measured, and browser find-in-page and screen readers only see mounted items.
content-visibility: autois a lighter alternative. - AWrap every item component in
- 16.easy
A dashboard shows live stock prices. Updates only flow from server to client, and you want automatic reconnection with minimal code over plain HTTP. What fits best?
- AWebSocket
- BServer-Sent Events (
EventSource) - CPolling the API every 100 ms
- DA WebRTC data channel
Show answer
Answer: B (Server-Sent Events (
EventSource))SSE is a one-way stream over HTTP with reconnection built into
EventSource, and it can resume usingLast-Event-ID. WebSockets are the better choice when the client also sends frequent messages (chat, multiplayer), but you implement reconnection and heartbeats yourself. - 17.hard
A chat client sends a message, the socket drops, and the client retries after reconnecting. How do you avoid duplicate messages and keep ordering correct?
- AOnly resend when the user presses Send again after reconnecting
- BOrder messages by the timestamp from each sender's device clock
- CGive each message a client id for idempotent retries; order by a server sequence number
- DSwitch from WebSockets to HTTP polling, which never duplicates messages
Show answer
Answer: C (Give each message a client id for idempotent retries; order by a server sequence number)
The server dedupes on the client id, so retrying is safe, and the client swaps its optimistic "sending" bubble for the confirmed message when the ack with that id arrives. Device clocks are skewed, so order should come from the server; sequence numbers also reveal gaps, which the client fetches after reconnecting.
- 18.mid
After a server deploy, 50,000 chat clients disconnect at the same moment. Which reconnection strategy avoids a thundering herd?
- AExponential backoff with random jitter, capped at a maximum delay
- BReconnect immediately in a tight loop
- CReconnect every second on a fixed interval
- DWait for the user to reload the page
Show answer
Answer: A (Exponential backoff with random jitter, capped at a maximum delay)
Exponential backoff spreads retries out while failures continue, and jitter desynchronizes clients so they don't all retry at the same instant. Also pause retries while the browser reports being offline and reconnect on the
onlineevent. - 19.easy
Which of these pieces of state belongs in the URL?
- AWhether a tooltip is open
- BThe auth access token
- CThe search query, filters and current page of a product list
- DThe value of a form input on every keystroke
Show answer
Answer: C (The search query, filters and current page of a product list)
State in the URL is shareable, bookmarkable, and survives reloads and back/forward navigation, which is exactly what users expect for search and filters. Ephemeral UI state stays local, and secrets never go in URLs because they end up in history, logs and
Refererheaders. - 20.mid
An e-commerce site has 200,000 product pages whose prices change a few times a day. Pages must be fast and SEO-friendly, and a full static rebuild takes hours. Which rendering strategy fits best?
- AClient-side rendering, with the API returning JSON only
- BStatic generation of all 200,000 pages on every build
- CServer-side rendering on every request, with caching disabled
- DIncremental static regeneration: serve cached pages, regenerate in the background
Show answer
Answer: D (Incremental static regeneration: serve cached pages, regenerate in the background)
ISR keeps the speed of static pages but regenerates each page after a revalidation window or when a webhook fires, so no full rebuild is needed; SSR behind a CDN with short cache lifetimes is a similar option. CSR hurts SEO and LCP, uncached SSR pays the rendering cost on every hit, and full SSG can't keep up with frequent changes across that many pages.
- 21.hard
A page's main content renders quickly, but its recommendations section depends on a 2-second API call. What does streaming SSR with Suspense-style boundaries improve over classic SSR?
- ANothing: the HTML is still sent only once every section is complete
- BThe main content arrives first; the slow section streams in when its data is ready
- CIt removes the need to hydrate the page on the client
- DIt makes the 2-second API call itself return faster
Show answer
Answer: B (The main content arrives first; the slow section streams in when its data is ready)
Classic SSR waits for all data before sending any HTML, so TTFB and FCP inherit the slowest dependency. Streaming flushes HTML progressively, with a fallback where the slow section will go, and frameworks can hydrate sections independently as they arrive.
- 22.mid
What is the strongest reason to adopt micro-frontends?
- ATo improve runtime performance by loading smaller apps
- BTo make it easier to share state between features
- CTo let autonomous teams build and deploy parts of a large app independently
- DTo be able to mix several frameworks on one page
Show answer
Answer: C (To let autonomous teams build and deploy parts of a large app independently)
Micro-frontends are an organizational scaling tool. They usually cost performance (duplicated dependencies, extra requests), consistency (design drift) and complexity (routing, shared state, versioning), so they pay off when team independence is the real bottleneck, not for a single small team.
- 24.mid
A news app's article API should show the latest content when online and the last cached version when offline. Which service worker caching strategy fits?
- ACache first
- BCache only
- CNetwork only
- DNetwork first, falling back to the cache
Show answer
Answer: D (Network first, falling back to the cache)
Network-first tries the network (often with a timeout), updates the cache on success, and falls back to the cached response when offline. Cache-first suits versioned static assets and the app shell; stale-while-revalidate suits resources where slightly stale is fine, like avatars.
- 25.easy
An offline-capable notes app needs to store thousands of structured notes, with attachments, on the device. Where should they go?
- AIndexedDB
- BlocalStorage
- CCookies
- DsessionStorage
Show answer
Answer: A (IndexedDB)
IndexedDB is asynchronous, stores structured data and Blobs, supports indexes and transactions, and has much larger quotas.
localStorageis synchronous (it blocks the main thread), stores only strings and is limited to a few megabytes; cookies are sent with every request. - 26.mid
How should an app produce messages like '1 file' / '5 files' in many languages?
- ATranslate both words and pick one with
count === 1 ? t('file') : t('files') - BAlways show 'file(s)' so one string works in every language
- CUse ICU plural messages or
Intl.PluralRules; plural rules differ by language - DConcatenate
count + ' ' + t('file')and let translators adjust the word
Show answer
Answer: C (Use ICU plural messages or
Intl.PluralRules; plural rules differ by language)Plural rules vary widely: Arabic has six categories, Polish distinguishes 'few' and 'many', and Japanese has a single form. An ICU message like
{count, plural, one {# file} other {# files}}lets translators handle each locale, and avoiding concatenation keeps word order translatable. - ATranslate both words and pick one with
- 27.mid
You're adding Arabic (right-to-left) support. How should component CSS express spacing like 'margin between the icon and the label'?
- AUse logical properties like
margin-inline-start, and setdir="rtl" - BMaintain a second stylesheet with every left and right swapped
- CApply
transform: scaleX(-1)to the body - DPosition every icon absolutely
Show answer
Answer: A (Use logical properties like
margin-inline-start, and setdir="rtl")Logical properties follow the writing direction, so one stylesheet works for both LTR and RTL once
diris set. Directional icons, such as back arrows, usually need mirroring too, while text itself should never be flipped with transforms. - AUse logical properties like
- 28.hard
You need to send session analytics when the user leaves the page, including on mobile. What is the most reliable approach?
- AA synchronous XHR inside an
unloadevent handler - BA normal
fetchcall inside abeforeunloadhandler - CKeep it in localStorage and send it on the user's next visit
- D
navigator.sendBeacon()whenvisibilitychangereports the page as hidden
Show answer
Answer: D (
navigator.sendBeacon()whenvisibilitychangereports the page as hidden)On mobile,
unloadandbeforeunloadoften don't fire because the page is backgrounded and then discarded, andunloadlisteners can also prevent the back/forward cache. The switch to hidden is the last event you can rely on, andsendBeacon(orfetchwithkeepalive: true) requests are allowed to outlive the page. - AA synchronous XHR inside an
- 29.mid
Production error reports show stack traces like
a.js:1:48213. How do you make them readable without publishing your source code?- ADisable minification in production builds
- BUpload source maps to the error tracker for each release, without serving them publicly
- CLog errors to the browser console instead of a tracker
- DWrap every function in try/catch to capture clearer messages
Show answer
Answer: B (Upload source maps to the error tracker for each release, without serving them publicly)
The error tracker uses the uploaded maps, matched by release, to de-minify stack traces. Serving
.mapfiles publicly also works but exposes your source. Tagging errors with release, route and browser makes regressions after a deploy easy to spot. - 30.easy
Lighthouse scores your page 98, but users on low-end Android phones complain that it is slow. What should you rely on to understand real performance?
- ARun Lighthouse several more times and average the scores
- BRe-test on a faster laptop with a stable connection
- CField data from real users (RUM or CrUX), segmented by device, at the 75th percentile
- DNothing more: the Lighthouse score is the Core Web Vitals result
Show answer
Answer: C (Field data from real users (RUM or CrUX), segmented by device, at the 75th percentile)
Lighthouse is a lab test on one simulated device and network, so it misses real devices, networks, caches and interactions (it can't measure INP at all). Core Web Vitals are assessed on field data at the 75th percentile. Collect RUM (for example with the
web-vitalslibrary) segmented by device class, and use lab tools to debug what it reveals. - 31.mid
A homepage carousel rotates automatically every 5 seconds. What does it need in order to be accessible?
- ANothing extra, as long as every slide image has alt text
- BA faster rotation so users can see every slide sooner
- CHiding all slides from screen readers with
aria-hidden - DA visible pause control, pausing on focus and hover, and honoring reduced motion
Show answer
Answer: D (A visible pause control, pausing on focus and hover, and honoring reduced motion)
WCAG requires a way to pause, stop or hide moving content that starts automatically and lasts more than five seconds. Respect
prefers-reduced-motion, label the slides (e.g. 'Slide 2 of 5'), make the controls keyboard-operable, and never move focus automatically when slides change. - 32.easy
A hero image is shown full-width on phones and at half width on desktops. How do you avoid sending a 2400px-wide file to phones?
- AUse
srcsetwith width descriptors plussizes, so the browser picks a file - BScale it down with CSS
width: 100%on small screens - CLazy-load it so phones only fetch it when it's visible
- DConvert it to PNG, which compresses photos better
Show answer
Answer: A (Use
srcsetwith width descriptors plussizes, so the browser picks a file)With
srcset="hero-800.jpg 800w, hero-1600.jpg 1600w, hero-2400.jpg 2400w"andsizes="(min-width: 1024px) 50vw, 100vw", the browser accounts for layout width and pixel density before downloading. Usepicturefor art direction or format fallbacks. CSS resizing still downloads the full file. - AUse
- 33.mid
A component library is used by several apps that need runtime theming, including dark mode, without rebuilding the library. What is the best approach?
- AHard-code colors in each component and publish a separate build per theme
- BPass every color to every component as a prop
- CShip Sass variables that each app must recompile
- DExpose design tokens as CSS custom properties that components reference, so apps override the variables at runtime
Show answer
Answer: D (Expose design tokens as CSS custom properties that components reference, so apps override the variables at runtime)
CSS variables cascade and can change at runtime, for example under a
[data-theme="dark"]selector or aprefers-color-schememedia query, so one build supports any theme. Semantic token names like--color-surfacekeep themes consistent across components. - 34.mid
How do you stop your banking app from being loaded in an invisible iframe on an attacker's site (clickjacking)?
- AServe the whole app over HTTPS with HSTS
- BMark all session cookies
HttpOnlyandSecure - CSend the CSP directive
frame-ancestors 'none'(orX-Frame-Options: DENY) - DAdd a CAPTCHA to every form and button
Show answer
Answer: C (Send the CSP directive
frame-ancestors 'none'(orX-Frame-Options: DENY))frame-ancestorstells the browser which origins may embed the page:'none'forbids framing entirely and'self'allows only your own origin.X-Frame-Optionsis the older header with the same purpose. HTTPS andHttpOnlyprotect other things.