Data Fetching Patterns: REST, GraphQL, tRPC & Real-time
Modern apps choose between REST (resource-based), GraphQL (client-shaped queries), tRPC (type-safe RPC), and real-time solutions (WebSockets/SSE) based on data complexity, freshness requirements, and developer experience.
REST = ordering individual dishes from a menu. GraphQL = customizing your meal exactly how you want. tRPC = ordering from your favorite local chef who knows you well. Real-time = the waiter keeps bringing updates as new dishes are ready.
REST
Resource endpoints
GraphQL
Client-defined queries
1REST
Resource-based architecture using standard HTTP methods. Simple, cacheable, and widely understood, but can lead to over/under-fetching.
2GraphQL
Client requests exactly the data needed in one query. Excellent for complex data relationships and multiple clients, but adds schema and resolver complexity.
3tRPC & gRPC-Web
tRPC provides end-to-end type safety for full-stack TypeScript. gRPC-Web offers efficient protobuf contracts for polyglot backends.
4Real-time Strategies
Polling for simplicity, WebSockets for bidirectional, SSE for server-push. Choose based on freshness needs and complexity tolerance.
| Property | REST | GraphQL | tRPC |
|---|---|---|---|
| Caching | Excellent (HTTP) | Challenging | Good |
| Best For | CRUD, public APIs | Complex data needs | Full-stack TypeScript apps |
| Complexity | Low | Medium | Low |
| Flexibility | Medium | Very High | High (TS-focused) |
REST
Caching
Excellent (HTTP)
Best For
CRUD, public APIs
Complexity
Low
Flexibility
Medium
GraphQL
Caching
Challenging
Best For
Complex data needs
Complexity
Medium
Flexibility
Very High
tRPC
Caching
Good
Best For
Full-stack TypeScript apps
Complexity
Low
Flexibility
High (TS-focused)
Common questions
- ›“When would you choose GraphQL over REST?”
- ›“What are the trade-offs of real-time data fetching?”
- ›“How does tRPC compare to GraphQL?”
- ›“How do you handle optimistic updates?”
What interviewers look for
- Clear reasoning based on data shape and freshness needs
- Understanding of over/under-fetching and caching
- Knowledge of optimistic vs pessimistic updates
- Practical architecture thinking
Short answer (60 sec)
REST for simple CRUD with good caching. GraphQL for complex, flexible queries. tRPC for type-safe full-stack TypeScript. Use real-time (WebSockets/SSE) when freshness is critical.
Detailed answer (senior level)
Choose based on needs: REST is simple and cache-friendly. GraphQL eliminates over/under-fetching but adds complexity. tRPC gives excellent DX in TS apps. Real-time solutions (WebSockets for bidirectional, SSE for push) are for live data. Combine with optimistic updates for great perceived performance.
- Using GraphQL for simple CRUD apps
- Over-fetching with REST without proper caching
- Ignoring N+1 problems in GraphQL
- Polling when WebSockets/SSE would be better
- Not separating client vs server state concerns
- ✓Match fetching strategy to data shape and freshness needs
- ✓REST: Simple, cacheable, widely understood
- ✓GraphQL: Flexible queries, single endpoint
- ✓tRPC: Best end-to-end TypeScript experience
- ✓Real-time: WebSockets for bidirectional, SSE for push
- ✓Optimistic updates improve perceived performance
- ✓Always consider caching, error handling, and loading states