Scalability has three axes: (1) traffic — handling more concurrent users without degrading latency; (2) code — keeping a growing codebase maintainable as teams and features multiply; (3) operational — debugging, deploying, and observing the system without heroics. Scalable apps invest in module boundaries, code splitting, caching layers, telemetry, and CI gates well before they're 'needed'.
Category
System Design
Frontend architecture for scale, micro-frontends, modular apps.
99 questions
Component structure: composition over inheritance, props down + events up, small focused components, design system primitives + domain compositions. State: local first (useState), lift only when shared, server state lives in a cache (React Query), global UI state in context or Zustand. Performance: SSR/SSG for first paint, code split per route, virtualize long lists, memoize on profiled-slow paths, lazy-load below fold, CDN + cache aggressively. Measure with RUM, set budgets in CI.
A whiteboard architecture round tests structured design thinking under ambiguity. Approach: clarify scope and constraints, sketch a high-level architecture, drill into APIs and data model, name scaling bottlenecks, and discuss trade-offs explicitly. Stay at the right altitude, use the whiteboard as an anchor, and invite the interviewer to drive depth. The goal is to show how you think, not to ship a perfect design in 45 minutes.
Structure: business context → user flows → architecture (rendering, state, routing, auth) → data layer (APIs, caching, realtime) → observability → key tradeoffs → what you'd change. Talk about decisions and constraints, not features. Bring a diagram.
Five OOP design principles: Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion. They aim for maintainable, decoupled code. In frontend they map to: focused components/hooks, extension via props/composition, consistent contracts, minimal prop interfaces, and depending on abstractions.
Pure functions are deterministic and side-effect-free: same inputs → same output, no I/O, no mutation of external state. They are trivially testable because they need no mocks, fixtures, or setup. Architecturally, the goal is to push impure code (fetch, DOM, time, randomness) to the edges and keep the core logic pure. This is the 'functional core, imperative shell' pattern that makes UIs predictable and refactorable.
Component-driven architecture builds UIs as compositions of small, independently developed, documented, and tested components. Build bottom-up: atoms → molecules → organisms → pages. Tools: Storybook for isolation + docs, design tokens for theming, a shared component library or design system. Benefits: reuse, consistency, parallel development, isolated testing. Costs: governance overhead, design-system maintenance, version coordination.
Scalability: code that survives growth in features, contributors, and data. Patterns: feature-folder structure, typed contracts at boundaries, small modules with single responsibilities, dependency direction (UI → domain → infra), monitoring, perf budgets, design-system tokens. Reuse: compose, don't configure; ship primitives + presets; document; favor narrow APIs over deep config.
Build a layered set: design-system primitives (Button, Input, Modal, Toast), composite components (DataTable, Form, Dropdown), layout primitives (Stack, Grid), and behavioral patterns/hooks (useDisclosure, compound components, render props). Reusability comes from good APIs, not just existence.
A context/store holding an array of toasts, an imperative API (toast.success(...)), a portal-rendered container, auto-dismiss timers, and per-toast config (type, duration, action). Discuss queueing, positioning, accessibility (aria-live), and animations.
Headless core (state + plugins) + thin UI shell. Composable APIs for column defs, sort, filter, pagination, selection, resizing. Server-side modes for big data. Virtualization for long lists. Adopt TanStack Table for the engine; build the design-system-styled UI on top. Avoid a god-component with 60 props.
Tree-shakable package with TypeScript types, accessible primitives (Radix-style headless + variants), tokens via CSS vars, semver + Changesets, Storybook + Chromatic, a11y + visual regression in CI, bundle-size budgets per component, and codemods for breaking changes. Ship ESM + types; consumers control styling via slots or className overrides.
Token-driven theming, headless primitives + styled wrappers, semantic-versioned releases, automated visual regression, and a contribution model that prevents fragmentation.
Design tokens + accessible primitives + clear ownership. Single source of truth for tokens (JSON → CSS vars + platform exports), unopinionated headless primitives, contribution model with RFCs + versioning, governance (a small core team), Storybook + visual regression, and automated migration codemods. Treat the DS as a product with its own roadmap, not a side project.
Key decisions: a small, intuitive surface; sensible defaults with progressive disclosure; consistency and naming; controlled vs uncontrolled; composition over configuration; TypeScript types as the contract; semver discipline; tree-shakability; minimal peer deps; good errors; and docs. Optimize for the consumer, and for change.
Ship ESM with named exports, mark `sideEffects: false` (or list the files that have them), avoid import-time side effects, prefer many small pure modules over barrels that pull everything, don't re-export huge namespaces, and keep modules pure so bundlers can drop what consumers don't use.
Scaffold with package.json, build to ESM (+ CJS) with TypeScript declarations, set exports/main/module/types fields and the files allowlist, version with semver, test and lint, then npm publish (with CI, provenance, and a changelog). Keep the API small and well-documented.
ESM (import/export) is statically analyzable → tree-shakable, the modern standard, works in browsers/bundlers. CJS (require/module.exports) is dynamic, the legacy Node format, not tree-shakable. Best practice: ship BOTH via package.json `exports` conditional exports, plus type declarations.
Semver strictly: breaking → major, additive → minor, fixes → patch. Use **Changesets** so every contributor's PR articulates the impact; CI consumes changesets to bump versions + write changelog. Pre-release channels (`next`, `canary`) for risky changes. Two-week stabilization. Maintain prior major branches with security patches. Codemods for breaking migrations.
Strict semver: breaking change → major. Use Changesets for changelog discipline. Mark APIs experimental with `@experimental` JSDoc. Deprecate with console.warn (or peer-dep typing) for one minor cycle before removing. Ship codemods for non-trivial migrations. Maintain release branches for the last 1–2 majors. Type-test with `tsd` / `expect-type` to catch unintended type changes.
Wrap everything in an IIFE/module so internals stay private via closure; expose exactly ONE namespaced, frozen global (window.Razorpay) whose methods are the public API. Guard against double-injection, avoid prototype pollution, and treat the global's shape as a stable contract.
`^1.2.3` allows any 1.x.x ≥ 1.2.3 (compatible-with-1.2.3). `~1.2.3` allows any 1.2.x ≥ 1.2.3 (patch only). Both stop at the next significant boundary; the difference is whether minors are allowed.
A peerDependency declares 'I need this, but the host app provides it' — used for shared singletons (React, a router) where multiple copies break things. The host installs one shared version; you don't bundle it. Use a wide version range; the host is responsible for satisfying it.
Diagnose via the changelog and the actual error; in the immediate term pin/rollback to unblock. Long term: lockfiles, semver discipline, isolating third-party deps behind wrappers, automated dependency updates with CI, and a regular upgrade cadence so changes are small.
Feature-folder structure (one folder per business domain) with explicit public APIs via index.ts barrel files. Layered concerns: app shell (routing, providers), features (business logic), shared (UI library, utilities). Boundaries enforced by lint plugins. Server state in React Query. Design system as a separate package or shared/ui folder. Tests, types, and styles colocated with components.
Feature-folder structure with UI → features → shared → lib dependency direction. Server state in React Query; client state in Zustand/RTK with selectors. Design system with accessible primitives. Per-route code splitting + RSC where applicable. CI gates: types, tests, bundle size, web-vitals, visual regression. ADRs for decisions. Codeowners per feature. Migrate incrementally with codemods.
Organize by feature domains, not by file type. Each module owns its UI, state, API calls, and types — and exposes a small public API. Enforce boundaries with lint rules (import restrictions), shared primitives only via a `core` package, and avoid cross-feature imports. Use TS path aliases, codeowners, and dependency-cruiser to keep the graph from collapsing.
Feature-based folder structure, shared packages for design system / utils, route-level code splitting, owned layouts per area, contracts at module boundaries.
Feature-folder structure (not type-based), route-level code splitting (one chunk per page), a design system shared across pages, server-state in React Query (per-page caching), client-state minimized and scoped, lazy-loaded heavy widgets, a strict module boundary (pages can't reach into siblings), CODEOWNERS per area, and bundle budgets enforced in CI. The hard part is organizational, not technical.
Routing strategy covers: URL → view mapping, code-splitting boundaries, data fetching (waterfalls vs parallel vs streaming), nested layouts, transitions and preloading, auth-gating, and history/scroll restoration. Modern frameworks (Next App Router, Remix, TanStack Router) ship opinionated answers; vanilla React Router needs explicit choices for each. Key trade-off: file-based routing (convention, instant DX) vs config-based (flexibility, explicit).
Responsive, mobile-first design with fluid layouts and breakpoints; a shared component library; adaptive (not just responsive) where capability differs; progressive enhancement; touch + pointer + keyboard input; performance budgets for low-end devices; and decide native vs web vs PWA per requirements.
Per-route (automatic in frameworks), per-heavy-widget (modals, editors, charts), per-locale, per-feature-flag. Vendor chunking by stability + usage (not one mega chunk). Prefetch likely-next routes on hover/viewport. Budget in CI (size-limit). Avoid waterfalls (chunk → loads → another chunk). RSC where possible (server-only code doesn't ship). Watch for over-splitting (HTTP overhead) and the loading-flash UX cost on the critical path.
Three intertwined concerns. SSR ships fully rendered HTML so first paint is fast (LCP wins) and crawlers see real content (SEO wins). SSG goes further by precomputing at build for static cacheable HTML. CSR alone leaves crawlers with an empty shell and pushes first paint past JS bundle download. Pick per page: SSG for marketing/blog, SSR/ISR for dynamic-but-shared content, CSR for authenticated dashboards. Layer in metadata (title, description, OG, JSON-LD), sitemap, canonical URLs.
Treat the local store as the source of truth; the network is an eventual-consistency partner. Cache shell assets via a Service Worker, persist data in IndexedDB (Dexie), queue mutations for replay on reconnect, and resolve merge conflicts via versioning or CRDTs. Surface offline state in the UI; never block the user on a request. Plan for partial connectivity (slow, flaky, captive portal), not just on/off.
Web Workers run JavaScript on a separate thread, off the main thread. They solve one core problem: CPU-bound work that would otherwise block paint, input, and animation. They do NOT solve I/O latency (fetch is already async) or render-blocking layout. Real wins: parsing large JSON, image/audio processing, crypto, search indexing, syntax highlighting. Communication is postMessage (structured clone or transferable), so picking the boundary is the hard part.
Five layers, each with its own home. Local UI state → useState. Form → React Hook Form. URL state → router params (shareable, back-button-friendly). Server data → React Query/RTKQ/SWR (cache, dedup, invalidation). Shared client state → Context for rarely-changing, Zustand/Jotai for frequently-changing slices. Persistent → localStorage + small store. Keep boundaries explicit; don't put server data in Redux or theme in Zustand if not needed.
Core: a store holding state, dispatch(action) → pure reducer → new state, and a subscribe mechanism. Add selectors with reference-equality memoization, middleware for async/side effects, and a React binding via useSyncExternalStore. RTK adds slices + Immer for ergonomics.
Above-the-fold + critical data: high priority, fetched immediately. Below-the-fold: low priority, fetched on idle / when visible. Use `priority` flag on requests, leverage `fetchpriority` attribute for resources, a queue that releases high before low, IntersectionObserver to upgrade priority when a component nears viewport, AbortController to cancel low-priority work when high-priority arrives.
Three layers. Cache: a data-fetching lib (React Query / RTKQ / SWR) with TTL, stale-while-revalidate, tag-based invalidation, and dedup. Retries: exponential backoff with jitter, only for idempotent methods, capped at 2-3 attempts; circuit-break after consecutive failures. Error boundaries: route-level and feature-level boundaries with fallback UIs, plus a global handler for unhandled rejections, plus log to monitoring (Sentry). Tie them together with a single fetch wrapper.
A client-side limiter that throttles outgoing requests: a token-bucket or sliding-window counter to cap request rate, a queue for excess requests, request deduplication and caching to reduce volume, plus respecting server 429s with backoff. The client limiter is UX/protection, not security.
Use CSS custom properties (variables) on :root, swap via a data-theme attribute. Apply theme on the server (or via an inline script BEFORE first paint) using a cookie/localStorage value to avoid flash. Provide system-default with prefers-color-scheme media query. Keep variable count manageable, organize semantic tokens (color-bg, color-text) over raw colors. Avoid JS-driven style mutation for performance.
A flag evaluator: flags defined with rules (boolean, user/role targeting, percentage rollout, environment, date windows), evaluated against a context (user, env). Expose via a provider + useFlag hook. Cache the evaluated flags, support remote config, and default safely when evaluation fails.
Use a flag service (LaunchDarkly/Unleash/Flagsmith or in-house) with typed flag definitions, evaluate flags with sensible defaults, support targeting/gradual rollout/kill switches, evaluate server-side where possible to avoid flicker, and enforce flag lifecycle hygiene so they don't become permanent tech debt.
Two flag types: release flags (kill-switch, gradual rollout — short-lived) and experiment flags (A/B with variants and metrics — bounded life). Evaluate server-side when possible to avoid bundle-time flicker; deliver to the client via a context provider and a stable hashing rule on user/session id. Bake in: targeting rules, percentage rollouts, sticky assignment, defaults that fail safe, dashboards, and a process to remove dead flags.
Evaluate flags server-side when possible, ship a typed flag client, default to OFF, kill-switch every change, and prune flags aggressively after launch.
Gate variants behind feature flags / an experimentation platform, assign users to stable buckets via consistent hashing, evaluate server-side (or pre-paint) to avoid flicker, keep the control path unchanged, instrument metrics, and ensure a clean kill switch and exposure logging.
A pipeline: on push → lint/test/build; on merge → deploy. Multiple environments (dev/staging/prod) each with its own config via env vars (not baked secrets). Branch/tag-based promotion, build-once-deploy-many, preview deploys per PR, and prod gated by approvals/checks.
Shared deps in a monorepo are managed by hoisting (single version at the root), workspace protocols (pnpm/yarn workspaces with workspace:* for internal packages), and version pinning via a single source of truth (single-version policy or syncpack). Tooling: pnpm/yarn/npm workspaces, Turborepo or Nx for task orchestration, changesets for versioning. Key tension: avoiding version drift across packages vs giving teams autonomy.
Strangler-fig pattern: strangle the legacy app route by route or feature by feature, not big-bang. Run old and new side-by-side behind a reverse proxy or feature flag; share auth/session via cookies; migrate the highest-value pages first; back the migration with metrics (perf, bug rate, conversion); kill the legacy code path only when usage is zero.
Avoid a big-bang rewrite. Assess and set goals, then migrate incrementally with the strangler-fig pattern — run old and new side by side, migrate route-by-route or feature-by-feature, keep shipping product, add tests as a safety net, and measure progress.
Layer it: error tracking (Sentry) for exceptions + source maps, RUM for real-user performance (Core Web Vitals), product analytics for behavior, and synthetic/uptime checks. Add error boundaries, global handlers, alerting with thresholds, release tracking, and PII scrubbing. The goal: know it broke before users tell you.
Capture errors (window handlers + boundaries), performance (Core Web Vitals via RUM), and structured logs/breadcrumbs; enrich with context (user, route, release, session); sample and rate-limit; route to a backend (Sentry/Datadog); add session replay and alerting on SLOs. Mind privacy.
OAuth 2.0 Authorization Code flow with PKCE: redirect to the provider, user consents, provider redirects back with a code, your backend exchanges it for tokens. Issue your own session (httpOnly cookie or short access + refresh token). Frontend never holds provider secrets; server validates everything.
Microfrontends extend microservice ideas to the UI: a single app is composed at runtime (or build time) from independently developed, deployed, and owned pieces. Each team ships their slice end-to-end. Composition via iframes, Module Federation, web components, or server-side includes. Trade-off: team autonomy and independent deploys vs. bundle duplication, version drift, and harder cross-team UX consistency.
Split the UI into apps owned by different teams that deploy independently. Composition: server-side stitching, build-time integration, runtime (Module Federation), or iframes. Independent deploys solve org coordination, not technical performance. The costs — bundle duplication, shared-state coupling, cross-app navigation, design consistency — are real; only adopt when org structure demands it.
Options: Module Federation shared dependencies (share React etc. as singletons), a versioned internal npm package / monorepo workspace, or import maps. Trade-offs: avoid duplicate bundles and version conflicts vs. coupling. Singletons matter for stateful libs like React; design-system and utils are good share candidates.
A small loader script injects an iframe hosting your checkout UI. The iframe isolates CSS/JS from the host page; postMessage (with strict origin checks) is the host↔widget channel. Concerns: namespace isolation, security (never trust the host), payment confirmation server-side, responsive overlay, versioning.
Open a WebSocket scoped to the order, render status from a server-pushed event stream, handle reconnection with backoff and state resync, fall back to SSE/polling, and keep the UI optimistic but reconcilable. Clean up the socket on unmount.
WebSocket connection authenticated at handshake, subscribed to a per-order channel. Server pushes status events; client merges into local state (TanStack Query cache or a simple reducer). Handle reconnection with backoff + resubscription, request a snapshot on connect to fill missed events, dedupe by event id, and fall back to polling on persistent failure. Consider SSE for one-way streams — simpler infrastructure, automatic reconnect.
Broadcast lightweight ephemeral events (cursor x/y, typing, presence) over a WebSocket, throttle cursor updates (~30-60ms) and interpolate on the receiving side, use heartbeats + timeouts for presence, and keep this transient data out of your persistent document state.
For collaborative editing, use CRDTs (Yjs/Automerge) or Operational Transformation to merge concurrent edits without conflicts. Send operations not snapshots, keep edits commutative/convergent, apply optimistic local updates, and reconcile via a server. For simpler cases, last-write-wins or field-level locking.
The core problem is conflict resolution on concurrent edits: OT (Operational Transformation) or CRDTs. Plus: a sync server (WebSockets), local-first optimistic edits, presence/cursors, document model + persistence, offline support, and undo/redo per-user. CRDTs (e.g. Yjs) are the modern go-to.
Streaming transport (WS or SSE) feeds a normalized client store; the UI subscribes to slices via selectors. Reconciliation, presence, conflict resolution, backpressure, reconnect/replay are explicit design choices.
Virtualize rows (and columns if wide), paginate/window the data, push heavy sort/filter/aggregation to the server or a Web Worker, apply real-time updates as targeted patches with batching/throttling, and keep the UI responsive with memoization and stable references.
LLMs (Large Language Models) are very large neural networks trained on massive text corpora for broad, capable language tasks. SLMs (Small Language Models) are compact models — fewer parameters — that trade some capability for lower latency, lower cost, on-device/edge deployment, and privacy.
AI is the broad field of systems performing tasks that need human-like intelligence (classification, prediction, recommendation, planning). Generative AI is a subset whose models create new content — text, images, code, audio — typically via large neural networks trained to model and sample from data distributions.
AI UIs must handle high/variable latency (stream + show progress), nondeterminism (no fixed 'correct' UI), hallucinations (don't present output as authoritative — enable verification, citations, editing), trust calibration, error/refusal handling, cost awareness, and giving users control (stop, regenerate, edit).
Never call the AI API directly from the browser — proxy through your own backend so the API key stays secret. The backend handles auth, rate limiting, prompt construction, and streaming; the frontend streams the response, renders incrementally, and handles loading/errors/cancellation.
The API returns a streaming response (SSE or chunked fetch). Read the ReadableStream from response.body, decode chunks, parse the token deltas, and append to state as they arrive. Handle partial chunks, abort/cancel, errors mid-stream, auto-scroll, and a 'stop generating' control.
Scalable LLM chat UI requires: streaming via SSE or fetch streams, optimistic message rendering, virtualized long conversation lists, persistent thread storage (server + optimistic local), abort/regenerate semantics, markdown + code-block rendering with syntax highlighting, tool-call / structured-output UI, multi-modal attachments, and careful state ownership (server is source of truth for history; client buffers active stream). Performance hot spots: re-rendering during token stream, scrolling pinned to bottom, markdown parsing on every token.
Designing and building 2D data structures (grids, matrices, sparse maps) involves choosing storage (dense array-of-arrays vs flat typed array vs sparse Map keyed by 'r,c'), defining mutation API, and reasoning about access patterns. Trade-off: dense storage is cache-friendly and indexable but wastes memory if sparse; sparse Maps save memory for empty cells but lose locality. Pick based on density and access pattern (random vs sequential, row-major vs column-major).
Debounced input → cached, cancellable suggestion requests → ranked results rendered in an accessible combobox. Cover debouncing, request cancellation/race handling, caching, keyboard nav + ARIA, highlighting, recent searches, and backend trie/search-service for suggestions.
Embeddable widget showing a question + options; user picks one, sees results with percentages and bar visuals. Optimistic UI on vote; idempotent vote (one per user/session, server-enforced); show results after voting or after deadline; real-time updates via polling or WebSocket; handle anonymous vs authed users; rate limit; embed via iframe or script.
Page composes `<Filters>`, `<ProductGrid>`, `<Pagination>`. URL is the source of truth for filters/sort/page (shareable, back-button safe). Server-side fetch + SSR/streaming for SEO; React Query handles client refetches on filter change. Skeleton states, optimistic UI on add-to-cart, image lazy-load + responsive srcset. A11y: filter region landmarks, announce result count.
Server-side filtering/search/pagination for scale; filters synced to the URL as the source of truth; product listing with cursor or page pagination; aggressive caching (React Query) per filter combination; virtualization or paginated grids; image optimization; and SSR/SSG for SEO and fast first paint.
Optimistic insert with a tempId → POST → reconcile on response. Local outbox queues failed sends with retry/backoff and offline support. WebSocket fan-out for receiving. Composer state separate from message list. Markdown / mentions / file uploads as composer plugins. Idempotency key on the request so retries don't duplicate.
Normalize: `messages: Map<id, Message>`, `channels: Map<id, Channel>`, `participants: Map<id, User>`, ordered `messageIdsByChannel: Map<channelId, id[]>`. Per-channel pagination cursors. Pending outbox keyed by tempId. Drafts per channel. Realtime updates merge into the normalized stores. UI selectors compute lists on demand. React Query for fetch + WebSocket for push.
WebSocket for real-time messaging; optimistic send with idempotency keys and per-message status (sending/sent/delivered/read); virtualized message list with cursor pagination (load older on scroll up); typing indicators via throttled events; presence via heartbeat; attachments uploaded separately and referenced by id; service worker for offline send queue; push notifications; e2e encryption optional but increasingly expected.
Real-time messaging UI: WebSocket connection for live messages, a normalized client store of chats/messages, optimistic sending with delivery states, virtualized message lists, offline queue + local persistence (IndexedDB), pagination of history, presence/typing, and reconnection handling.
Infinite-scroll feed with cursor pagination; virtualized list for large scrolls; per-post components with mixed media; optimistic likes/comments; ranking served by backend; client caches via React Query keyed on cursor; image/video lazy-load; offline / poor-network resilience; accessibility for the post structure and live updates.
Covered in depth at [[frontend-system-design-design-a-news-feed-facebook]]. The headline architecture: cursor-paginated server-ranked feed, virtualized list, memoized post components, optimistic likes/comments with idempotency keys, lazy + responsive media, real-time updates via WebSocket or polling, SSR/SSG for first paint and SEO, service worker shell for offline-friendly repeat loads.
Vertical infinite-scroll feed of posts (image/video, caption, likes, comments). Cursor-paginated, virtualized for memory; aggressive image/video lazy-load with placeholders and autoplay-on-visible; optimistic likes/comments; stories carousel above feed; pull-to-refresh; double-tap-to-like; SSR/SSG home for SEO; service worker for offline shell.
Photo-first social product: feed (see [[design-an-instagram-like-feed-page]]) + upload flow + profile + explore. Upload: client crops/filters → direct-to-S3 pre-signed URL → post-process server-side → create post referencing uploaded media. Heavy image optimization (responsive srcset, modern formats, blurhash). Stories (24h ephemeral), DMs, search/explore powered by server.
Masonry-grid pinboard with infinite scroll over cursor-paginated server feed; variable-height tiles requiring a packing algorithm (CSS columns or JS positioning); virtualization for long boards; aggressive image optimization with placeholders; pin/save interactions optimistic; SSR/SSG for SEO; accessible grid + keyboard nav.
Break out into Board / Column / Card components. State shape keyed by id with column → ids ordering. APIs for move/reorder via optimistic updates. Discuss scalability (virtualization, pagination), offline, real-time, and accessibility.
Model columns and cards as normalized state, render columns mapping over ordered card-id lists, implement drag-and-drop with optimistic reordering, persist moves to the server, and handle real-time multi-user sync, virtualization for big boards, and conflict resolution.
Day/week/month views with virtualized scrolling; events as positioned blocks computed by collision/layout algorithm; offline-capable via IndexedDB + sync queue; recurring events expanded client-side per visible range; drag-to-create and drag-to-move with optimistic updates; timezone-aware; keyboard + accessibility; real-time updates for shared calendars.
Time-based grid (day/week/month). Events stored normalized with start/end + recurrence rule (RRULE). Render by computing visible occurrences for the current view. Handle overlap layout, drag-to-create/move, and timezones.
HLS/DASH adaptive bitrate streaming via a player (Shaka/Video.js) sourced from a CDN; manifest + segmented chunks; ABR algorithm picks quality based on bandwidth + buffer; preload posters and metadata; SSR/SSG the catalog pages for SEO and fast LCP; per-row carousels; auth-gated playback; accessibility (captions, focus, keyboard).
Mostly a backend-leaning design: transaction flow (auth → capture), idempotency keys to prevent double-charges, a double-entry ledger as source of truth, state machines for transaction status, async webhooks for settlement, retries with exponential backoff, and reconciliation. Frontend role: never trust the client; confirm server-side.
Mobile-first driver app: live route on a map (GPS subscription, Map SDK), current/next stop card with ETA, multi-order queue, status transitions (assigned → picked → delivered) with optimistic updates and offline queue, navigation handoff to Google/Apple Maps, push notifications, background location, low-battery considerations, accessible large-touch UI.
Lock screen → home with app grid → app screens; each app a self-contained route. State: current app (route), back-stack, modal layer, notifications. App registry pattern: each app declares its icon, name, route, and entry component. Status bar + dock fixed; gesture/keyboard nav between screens. Lazy-load each app's bundle.
OOP LLD with clear responsibilities: `ATM` (state machine: idle → authenticated → operating), `Card` (number, expiry, validate), `BankAccount` (balance, withdraw, deposit, transactions), `Transaction` (type, amount, status, ts), `CashDispenser` (inventory by denomination, dispense algorithm), plus a bank service for auth/balance. State machine on the ATM and transactional consistency are the depth pieces.
Designing features like tabs, history/back-forward, bookmarks, find-in-page, or a mini-renderer. Model the state machine, choose the right data structures (stacks for history, trees for the DOM), handle persistence and lifecycle, manage memory, and reason about performance and edge cases.
Tile-based map: world is divided into z/x/y tiles per zoom level (~256x256 px). Load only visible tiles + small overscan. Use HTTP/2 multiplexing for parallel tile fetches; long-cache hashed tile URLs at the edge. Off-main-thread tile decode via OffscreenCanvas or web worker. Render via Canvas/WebGL — DOM doesn't scale. Pan/zoom via CSS transforms + RAF, not per-event DOM mutations. Predict next-likely tiles (direction of pan) and prefetch. Vector tiles + WebGL for richer interactions.
Cursor-based pagination + an IntersectionObserver sentinel that triggers loading the next page. Accumulate pages, track hasMore/nextCursor and loading state, virtualize the list, handle errors with retry, and address scroll restoration. Cursor (not offset) keeps it stable under inserts.
Combine cursor-based pagination (fetch in pages as the user nears the end) with virtualization (render only the visible window). Use IntersectionObserver to trigger loads, cache pages, handle loading/error/end states, and preserve scroll position. Never hold all items in the DOM or in one fetch.
A realtime gaming dashboard needs sub-second latency for game state, leaderboards, and player stats. Architecture: WebSocket for live state, SSE or polling for slower updates, edge pub/sub fan-out (Redis / NATS), CDN-cached snapshots for cold loads, virtualized leaderboard rendering. Critical concerns: backpressure, reconnect, last-write-wins ordering, fairness during partial outages, anti-cheat read paths. Trade-off: WebSocket fan-out scales horizontally but adds infra; SSE is simpler but one-way.
Edge-first: static assets + ideally HTML on CDN (Cloudflare/Fastly/Vercel Edge). SSG for content, SSR/ISR for personalized. Aggressive caching with hashed assets + tag-based invalidation. Service worker for repeat-visit speed. Per-route code splitting + bundle budgets in CI. RUM (web-vitals) sampled, alerted on regression. Observability: error monitoring (Sentry), perf dashboard. Multi-region origin if SSR. Resilience: circuit breakers, retries, graceful degradation. Cost-aware: cap third-party tags, optimize images, lazy below-fold.