Frontend System Design

The RADIO Framework for Frontend System Design

5 min read

Frontend system design interviews test a completely different skill set than backend system design. While backend focuses on databases, load balancers, and distributed systems, frontend system design focuses on component architecture, state management, rendering performance, and user experience.

How Frontend Differs from Backend System Design

Aspect Backend System Design Frontend System Design
Focus Scalability, storage, throughput Responsiveness, rendering, UX
State Database, cache, message queues Component state, URL, local storage
Network Service-to-service communication API calls, real-time connections
Failure Server crashes, network partitions Offline mode, slow connections
Scale Millions of requests/second 60fps rendering, bundle size

The RADIO Framework

RADIO gives you a repeatable structure for any frontend system design question. Walk through each step in order:

R - Requirements    → Clarify scope and constraints
A - Architecture    → Component tree and page layout
D - Data Model      → State shape, where it lives, how it flows
I - Interface       → API contracts between components and server
O - Optimization    → Performance, accessibility, edge cases

Step 1: Requirements

Spend the first 3-5 minutes asking clarifying questions. Split requirements into functional and non-functional:

Functional requirements (what it does):

  • What are the core user actions?
  • What data is displayed?
  • What interactions are supported?

Non-functional requirements (how well it does it):

  • How many concurrent users?
  • What devices and browsers must be supported?
  • What latency targets? (e.g., search results under 200ms)
  • Offline support needed?
  • Accessibility requirements (WCAG level)?

Step 2: Architecture

Sketch the component tree. Start with the page-level layout, then drill into each section:

<App>
  ├── <Header>
  │    ├── <Logo />
  │    ├── <SearchBar />
  │    └── <UserMenu />
  ├── <Sidebar>
  │    └── <Navigation />
  └── <MainContent>
       ├── <FilterPanel />
       └── <ResultsList>
            └── <ResultCard /> (repeated)

Key decisions to explain:

  • Which components are smart (stateful) vs. dumb (presentational)?
  • Where do you split the component boundary?
  • Which components are lazy-loaded?

Step 3: Data Model

Define the state shape and where each piece of state lives:

// Server state (fetched, cached via TanStack Query or SWR)
interface ServerState {
  products: Product[];
  userProfile: User;
  notifications: Notification[];
}

// Client state (local to the UI)
interface ClientState {
  searchQuery: string;
  selectedFilters: Filter[];
  isModalOpen: boolean;
  currentPage: number;
}

// URL state (shareable, bookmarkable)
interface URLState {
  category: string;    // /products?category=electronics
  sortBy: string;      // /products?sort=price-asc
  page: number;        // /products?page=3
}

State management decision tree:

State Type Where It Lives Tool
Server data Cache layer TanStack Query, SWR
Global UI state External store Zustand, Redux Toolkit
Local UI state Component useState, useReducer
URL-dependent URL params useSearchParams, router
Form data Form library React Hook Form, Formik

Step 4: Interface (API Layer)

Define the contracts between your frontend and the server:

// REST API design
GET    /api/products?q=laptop&category=electronics&page=1&limit=20
POST   /api/products          // create
PATCH  /api/products/:id      // partial update
DELETE /api/products/:id      // delete

// Response shape
interface APIResponse<T> {
  data: T;
  pagination: {
    page: number;
    totalPages: number;
    totalItems: number;
  };
  error?: { code: string; message: string };
}

REST vs. GraphQL decision:

Factor REST GraphQL
Multiple resources Multiple round trips Single query
Overfetching Returns full objects Request exact fields
Caching HTTP cache-friendly Needs normalized cache
Team setup Simpler to start Needs schema + tooling

Real-time updates strategy:

Method Use When Overhead
Polling Low-frequency updates (every 30s+) Low complexity
SSE Server pushes events one-way (notifications, feeds) Medium
WebSocket Bidirectional real-time (chat, collaboration) Highest

Step 5: Optimization

This is where you differentiate yourself. Cover:

Rendering performance:

  • Virtualized lists for long scrolling content (react-window, TanStack Virtual)
  • Code splitting with React.lazy() and route-based chunking
  • Optimistic updates for perceived speed

Network performance:

  • Request deduplication and caching
  • Prefetching on hover or route proximity
  • Image optimization (lazy loading, srcset, WebP/AVIF)

Accessibility:

  • Keyboard navigation for all interactive elements
  • ARIA attributes for custom widgets
  • Focus management on route changes

Edge cases:

  • Offline mode with service worker caching
  • Error boundaries for graceful failure
  • Empty states, loading states, error states

Practical Example: RADIO Applied to a Search Page

Let us walk through RADIO for a product search page:

R (Requirements): Users search products by keyword, filter by category and price, sort results, paginate through them. Must work on mobile. Target: results in under 200ms.

A (Architecture):

<SearchPage>
  ├── <SearchBar />          // debounced input
  ├── <ActiveFilters />      // chips showing current filters
  ├── <FilterSidebar />      // category, price range
  └── <ResultsPanel>
       ├── <SortControls />  // relevance, price, rating
       ├── <ProductGrid>
       │    └── <ProductCard /> (repeated)
       └── <Pagination />

D (Data Model): Search query and filters live in URL params (shareable). Products are server state cached by TanStack Query with the query string as cache key.

I (Interface): GET /api/search?q=laptop&category=electronics&minPrice=500&sort=price-asc&page=1 returns paginated results with facet counts.

O (Optimization): Debounce search input by 300ms. Prefetch next page. Virtualize product grid on mobile. Use <img loading="lazy">. Add aria-live="polite" region for screen reader announcements when results update.

Interview tip: Always draw the component tree and state flow on the whiteboard. Interviewers want to see your thought process, not just hear it.

Next, we will walk through three classic frontend system design problems step by step. :::

Quiz

Module 4: Frontend System Design

Take Quiz