Skip to main content

RADIO Framework

The RADIO framework is a checklist for structuring frontend system design discussions. It moves from understanding the problem to proposing a design and then examining the parts where deeper trade-offs matter.

R -> Requirements
A -> Architecture
D -> Data Model
I -> Interface Definition
O -> Optimizations and Deep Dive

One-line idea: RADIO keeps a design grounded in requirements before moving through architecture, data, contracts and evidence-driven optimization.

Core Concepts​

What RADIO Is - and Is Not​

RADIO is a practical interview and design heuristic, not a formal web standard or a rigid development process. Its purpose is to make open-ended reasoning complete and easy to follow.

Understand the product
↓
Draw the major boundaries
↓
Define the information
↓
Specify communication
↓
Stress-test important decisions

The stages influence one another. Discovering an API limitation may change the data model; a performance target may change the architecture. Use the letters as checkpoints and revisit earlier decisions when needed.

R - Requirements​

Requirements establish what must be designed, for whom and under which constraints. Do this before choosing frameworks, state libraries or rendering strategies.

Functional Requirements​

Functional requirements describe user-visible behavior.

For a news feed, important questions might include:

  • Can users only read posts, or also create and edit them?
  • Is the feed chronological, ranked or both?
  • Are reactions, comments and sharing in scope?
  • Must new posts appear in real time?
  • Does the feed support search, filtering or offline reading?

Identify the critical user journeys and separate them from optional features.

Must have: View feed, load more, open a post
Useful: React, comment, refresh in real time
Later: Offline mode, advanced filters

Non-Functional Requirements​

Non-functional requirements describe the quality and operating constraints of the experience:

  • performance and responsiveness
  • accessibility
  • availability and reliability
  • scale and traffic patterns
  • security and privacy
  • internationalization
  • browser and device support
  • SEO and shareability
  • offline or low-connectivity behavior

Make important goals measurable where possible:

Vague:    The feed should be fast.
Specific: The first page should remain usable on a mid-range mobile device
and scrolling should not require rendering thousands of DOM nodes.

Scope and Assumptions​

State what the design will and will not cover:

In scope:  Web client, feed rendering, pagination and optimistic reactions
Out of scope: Post recommendation algorithm and media transcoding
Assumption: Backend APIs and authentication service already exist

This prevents time from being spent on a different problem than the one being evaluated.

Requirements Output​

At the end of this stage, aim to have:

  • primary users
  • critical use cases
  • important constraints
  • scale assumptions
  • explicit exclusions
  • a few success signals

A - Architecture​

Architecture shows the major components, boundaries and data flow that satisfy the requirements.

Browser
├── Routes and page shell
├── Feature components
├── Client and server state
└── Data-access layer
↓
API gateway or backend services
↓
Databases, caches and external systems

Keep the first diagram high-level. Explain why each major block exists before discussing implementation details.

Frontend Questions​

Consider:

  • How are routes and feature boundaries organized?
  • Which pages use CSR, SSR, SSG or a hybrid?
  • Which state is local, shared, server-owned or URL-based?
  • How does data flow through the interface?
  • What should happen during loading, empty and failure states?
  • Which features load initially and which can be deferred?
  • Where are authentication and authorization enforced?

Component Boundaries​

Prefer components with clear responsibilities:

FeedPage
├── FeedFilters
├── FeedList
│ └── FeedItem
└── PaginationSentinel

Avoid turning a component tree into the entire architecture. Also show data ownership, network boundaries, caching and important browser capabilities.

Data Flow​

Trace at least one important user action from input to visible result:

User reacts to a post
↓
UI applies optimistic state
↓
Mutation is sent with post and reaction IDs
↓
Server accepts or rejects the request
↓
UI confirms or rolls back the optimistic update

This exposes missing loading states, race conditions and ownership decisions earlier than a box diagram alone.

Architecture Output​

Produce:

  • a high-level component and service diagram
  • rendering and routing choices
  • state ownership boundaries
  • one or two key data flows
  • failure and recovery behavior
  • reasons for major decisions

D - Data Model​

The data model defines the information the frontend reads, derives, caches and changes.

Identify Entities​

Start with product concepts rather than UI components:

type User = {
id: string;
displayName: string;
avatarUrl: string;
};

type Post = {
id: string;
authorId: string;
body: string;
createdAt: string;
reactionCount: number;
};

Discuss identifiers, relationships, optional fields and update frequency. Clarify which values come from the server and which are derived by the client.

Classify State​

State typeExampleTypical owner
Local UI stateOpen menu, draft inputComponent or feature
URL stateSearch query, filter, selected tabRouter or URL
Server stateFeed items, user profileQuery cache backed by server
Shared client stateTheme, session summaryApplication-level store or context
Persistent client stateOffline drafts, preferencesBrowser storage with a lifecycle policy

Do not put every value in global state. Keep state close to its owner while providing a deliberate synchronization path when multiple consumers need it.

Normalize When It Solves a Problem​

Repeated entities may be stored once and referenced by ID:

const state = {
usersById: {
u1: { id: "u1", displayName: "Aman" },
},
postsById: {
p1: { id: "p1", authorId: "u1", body: "Hello" },
},
feedIds: ["p1"],
};

Normalization can reduce duplication and simplify consistent updates. It also adds lookup and reconstruction work, so use it where entities are shared or frequently updated rather than automatically.

Model UI States Explicitly​

Include more than successful data:

type RequestState<T> =
| { status: "idle" }
| { status: "loading" }
| { status: "success"; data: T }
| { status: "error"; message: string };

Loading, empty, stale, partial and error states are part of the product design.

Data Model Output​

Produce:

  • core entities and relationships
  • state categories and owners
  • update and invalidation rules
  • derived values
  • loading and failure states
  • persistence and retention decisions

I - Interface Definition​

Interfaces are contracts between components, modules, clients, services and third parties.

Network API Contracts​

Define the information a client needs rather than only naming an endpoint:

GET /api/feed?cursor=abc123&limit=20
{
"items": [
{
"id": "p1",
"authorId": "u1",
"body": "Hello",
"createdAt": "2026-09-04T10:00:00Z"
}
],
"nextCursor": "def456"
}

Discuss:

  • request and response shapes
  • pagination and filtering
  • authentication
  • validation and error formats
  • retries, cancellation and timeouts
  • versioning and backward compatibility
  • real-time events when required

Component Interfaces​

Frontend interfaces also include props, callbacks and events:

type FeedItemProps = {
post: Post;
currentUserReaction?: string;
onReact: (postId: string, reaction: string) => void;
};

A useful component contract exposes product behavior without leaking internal markup or state-management details.

Event Contracts​

For real-time systems, describe event identity and ordering:

{
"type": "post.updated",
"eventId": "evt_42",
"postId": "p1",
"version": 7,
"changes": {
"reactionCount": 13
}
}

Version or sequence information can help the client reject stale updates and recover after reconnecting.

Interface Output​

Produce:

  • main network requests and events
  • representative payloads
  • component or module contracts
  • error and cancellation behavior
  • compatibility and evolution strategy

O - Optimizations and Deep Dive​

Start optimization only after a complete baseline design exists. Choose the areas most connected to the stated requirements and likely bottlenecks.

Performance​

Possible topics include:

  • route and feature code splitting
  • image and font delivery
  • list virtualization
  • memoization after measuring renders
  • caching and request deduplication
  • pagination or incremental loading
  • prefetching likely next actions
  • Web Workers for CPU-heavy processing

Explain the cost as well as the benefit. Prefetching may improve navigation but consume bandwidth; aggressive caching may serve stale data.

Reliability and Network Behavior​

Consider:

  • retry rules with backoff
  • offline and reconnect behavior
  • optimistic update rollback
  • duplicate or out-of-order events
  • stale cache revalidation
  • graceful degradation
  • feature rollback or kill switches

Accessibility and Internationalization​

Check:

  • semantic structure and accessible names
  • keyboard and focus behavior
  • announcements for dynamic updates
  • contrast and reduced motion
  • translated text expansion
  • locale-aware dates and numbers
  • left-to-right and right-to-left layouts

These are requirements and design constraints, not polish to add after performance work.

Security and Privacy​

Cover the risks relevant to the feature:

  • authentication and authorization boundaries
  • output encoding and input validation
  • CSRF and XSS protection
  • safe token and sensitive-data handling
  • content security policy
  • permission minimization
  • logging without exposing private data

Frontend checks improve user experience but do not replace server-side authorization.

Observability​

Define signals that show whether the design works in production:

  • user-centric performance metrics
  • request latency and failure rate
  • JavaScript errors
  • feature-specific success and abandonment rates
  • structured logs and trace correlation
  • alerts tied to user impact

Optimization should be connected to measurements and an explicit success criterion.

Requirements​

  • Show suggestions after the user types a short query.
  • Support keyboard and screen-reader interaction.
  • Keep results responsive on unreliable networks.
  • Do not send a request for every keystroke.

Architecture​

SearchInput
↓ debounced query
SuggestionController
↓ cached request
Search API
↓
AccessibleSuggestionList

Data Model​

type AutocompleteState = {
query: string;
suggestions: Suggestion[];
activeIndex: number;
status: "idle" | "loading" | "success" | "error";
};

Interface​

GET /api/suggestions?q=rea&limit=8

The response includes stable suggestion IDs, display labels and optional destination URLs.

Optimization and Deep Dive​

  • Debounce input while keeping typing immediate.
  • Cancel or ignore stale requests.
  • Cache recent queries for a short period.
  • Limit and rank the response on the server.
  • Use combobox semantics and predictable keyboard navigation.
  • Measure response latency, selection rate and abandoned searches.

The example shows how each step narrows the next. The optimizations follow from the latency, accessibility and request-volume requirements.

Using RADIO Effectively​

Treat It as a Checklist​

RADIO does not require equal time for every letter. Begin with requirements, sketch the whole design, then spend depth where the problem is difficult or the interviewer shows interest.

Broad pass: R -> A -> D -> I -> O
Deep dive: A <-> D <-> I <-> O

Explain Trade-Offs​

Avoid listing technologies without reasoning:

Weak:   Use WebSockets.
Better: Use WebSockets because updates are bidirectional and frequent;
for server-only notifications, SSE would be simpler.

State the selected option, the requirement it satisfies, its cost and when an alternative would be better.

Common Mistakes​

MistakeBetter approach
Choosing a framework before clarifying the productStart with users, flows, constraints and scope
Treating RADIO as a rigid scriptRevisit stages as new information changes the design
Drawing only a component treeInclude state, data flow, server boundaries and failures
Modeling only successful dataInclude loading, empty, stale, partial and error states
Defining endpoints without contractsShow representative fields, errors, pagination and evolution
Putting all state in one global storeClassify state and keep ownership deliberate
Listing every possible optimizationPrioritize bottlenecks tied to requirements
Ignoring accessibility or security until the endTreat them as constraints throughout the design
Claiming one architecture is always bestCompare alternatives and explain the chosen trade-off
Spending the interview on implementation codeFocus on design decisions unless code is requested

References and Further Reading​

Summary​

RADIO structures frontend system design by connecting requirements to architecture, data ownership, communication contracts and prioritized optimization.

Clarify the user problem and constraints
↓
Design the simplest architecture that satisfies them
↓
Make data ownership and state transitions explicit
↓
Define stable contracts between boundaries
↓
Deep-dive into the highest-impact risks and trade-offs
↓
Validate every major choice against a requirement