惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

宝玉的分享
宝玉的分享
酷 壳 – CoolShell
酷 壳 – CoolShell
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
S
Security @ Cisco Blogs
小众软件
小众软件
D
Docker
博客园_首页
A
About on SuperTechFans
P
Privacy International News Feed
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
A
Arctic Wolf
Spread Privacy
Spread Privacy
有赞技术团队
有赞技术团队
T
Tailwind CSS Blog
Latest news
Latest news
WordPress大学
WordPress大学
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
T
The Exploit Database - CXSecurity.com
C
Cybersecurity and Infrastructure Security Agency CISA
大猫的无限游戏
大猫的无限游戏
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
K
Kaspersky official blog
V2EX - 技术
V2EX - 技术
SecWiki News
SecWiki News
U
Unit 42
GbyAI
GbyAI
H
Hackread – Cybersecurity News, Data Breaches, AI and More
L
LINUX DO - 热门话题
S
Security Affairs
Y
Y Combinator Blog
aimingoo的专栏
aimingoo的专栏
Blog — PlanetScale
Blog — PlanetScale
MongoDB | Blog
MongoDB | Blog
博客园 - 【当耐特】
The GitHub Blog
The GitHub Blog
T
Tenable Blog
W
WeLiveSecurity
Cloudbric
Cloudbric
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
G
Google Developers Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
N
Netflix TechBlog - Medium
F
Full Disclosure
N
News and Events Feed by Topic
D
DataBreaches.Net
P
Proofpoint News Feed
B
Blog RSS Feed
B
Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
System Design - 12. REST vs GraphQL vs gRPC: Choosing the Right API for Every Job
Rajkiran · 2026-06-11 · via DEV Community

REST vs GraphQL vs gRPC: Choosing the Right API for Every Job

Covers: REST, GraphQL, gRPC, API Gateway, BFF Pattern, Rate Limiting, API Versioning


The API That Cost Stripe Millions

In 2013, Stripe had a problem. Their REST API was so well-designed that developers around the world loved it. Businesses built entire payment flows on it.

Then they needed to make a breaking change.

They couldn't just update the API — thousands of businesses would instantly break. They couldn't force everyone to migrate overnight. So Stripe did something brilliant: they maintained multiple API versions simultaneously, routing each client to the version it was built against.

Today Stripe supports API versions going back to 2011. Every version is still alive. Every old integration still works.

The cost? A dedicated versioning infrastructure, careful compatibility testing across every version for every change, and an engineering team focused purely on API stability.

The lesson: API design decisions compound over years. The choice of REST, GraphQL, or gRPC — and how you version, gateway, and rate-limit your API — determines your architecture's flexibility for the next decade.

Let's make these decisions well.


REST: The Universal Language of the Web

REST (Representational State Transfer) is an architectural style built around HTTP verbs and resource URLs. It's been the dominant API style since Roy Fielding defined it in his 2000 dissertation.

REST's 6 Principles

1. Stateless       — Every request contains all info needed. No server-side sessions.
2. Client-Server   — Frontend and backend are independent. Either can change.
3. Cacheable       — Responses declare whether they can be cached.
4. Uniform Interface — Standard HTTP verbs + resource URLs.
5. Layered System  — Client doesn't know if it's talking to server, cache, or LB.
6. Code on Demand  — (optional) Server can send executable code to client.

REST in Practice

Resources are nouns. HTTP verbs are actions.

GET    /users/123          → Retrieve user 123
POST   /users              → Create a new user
PUT    /users/123          → Replace user 123 entirely
PATCH  /users/123          → Partially update user 123
DELETE /users/123          → Delete user 123

GET    /users/123/orders   → Get orders belonging to user 123
POST   /users/123/orders   → Create an order for user 123

HTTP status codes carry meaning:

200 OK            → success, body contains data
201 Created       → resource created (POST success)
204 No Content    → success, no body (DELETE success)
400 Bad Request   → client sent invalid data
401 Unauthorized  → not authenticated
403 Forbidden     → authenticated but not allowed
404 Not Found     → resource doesn't exist
409 Conflict      → state conflict (e.g., duplicate email)
422 Unprocessable → valid format but business rule violation
429 Too Many Req  → rate limited
500 Server Error  → something broke on our side

REST is cacheable by design:

GET /products/456
Cache-Control: max-age=3600  → Cache this for 1 hour
ETag: "abc123"               → Fingerprint for conditional fetches

GET requests are idempotent and safe — CDNs and browsers can cache them aggressively.

REST's Weakness: Over and Under-Fetching

Over-fetching: The API returns more data than the client needs.

GET /users/123

Response:
{
  "id": 123,
  "name": "Priya Sharma",
  "email": "priya@example.com",
  "phone": "...",
  "address": "...",
  "billing_info": { ... },   client only needed name and email
  "subscription": { ... },   but gets everything
  "preferences": { ... }
}

The mobile client wanted to display "Hello, Priya" and got 50 fields. Wasteful on mobile bandwidth and battery.

Under-fetching: The client needs multiple requests to get all the data it needs.

// Show a user's feed: need user + their posts + each post's comments

GET /users/123           → 1 request
GET /posts?user_id=123   → 1 request
GET /comments?post_id=1  → 1 request per post (N+1 problem!)
GET /comments?post_id=2
GET /comments?post_id=3
...                      → Could be dozens of requests for one screen

These problems become severe on mobile networks and led to the creation of GraphQL.


GraphQL: The Client Takes Control

GraphQL was created by Facebook in 2012 (open-sourced 2015) to solve the over/under-fetching problem that was killing their mobile app performance.

The core insight: let the client declare exactly what data it needs, and return only that.

How GraphQL Works

A single endpoint (/graphql) accepts queries describing exactly what the client wants:

query GetUserFeed {
  user(id: "123") {
    name                    # ← only the fields we need
    posts(first: 10) {      # ← only 10 posts
      title
      createdAt
      comments(first: 3) {  # ← only 3 comments per post
        text
        author {
          name              # ← just the name, not full profile
        }
      }
    }
  }
}

One request. Exactly the data the client needs. Nothing more.

Server response:

{
  "data": {
    "user": {
      "name": "Priya Sharma",
      "posts": [
        {
          "title": "My first post",
          "createdAt": "2024-01-15",
          "comments": [
            { "text": "Great!", "author": { "name": "Arjun" } }
          ]
        }
      ]
    }
  }
}

GraphQL Mutations and Subscriptions

# Mutation — modifying data
mutation CreatePost {
  createPost(input: { title: "Hello World", content: "..." }) {
    id
    title
    createdAt
  }
}

# Subscription — real-time updates via WebSocket
subscription OnNewComment {
  commentAdded(postId: "456") {
    text
    author { name }
  }
}

GraphQL's Real Trade-offs

Advantages:

  • Eliminates over/under-fetching — mobile apps love this
  • Single endpoint, self-documenting schema
  • Strong type system catches errors at compile time
  • Excellent developer tooling (GraphiQL playground, code generation)
  • Enables rapid frontend iteration without backend API changes

Disadvantages:

  • Caching is hard: POST to /graphql is not cacheable by default (CDNs cache by URL). Requires persisted queries or specialized GraphQL CDN caching.
  • N+1 query problem: A naive GraphQL implementation can fire hundreds of database queries for one client request. Requires DataLoader (batching) to fix.
  • Complex queries can be expensive: A malicious or poorly written client can request deeply nested data that destroys your database. Requires query depth limiting and cost analysis.
  • Overkill for simple APIs: If your API is a handful of straightforward endpoints, GraphQL's complexity isn't worth it.

Who uses it: Facebook (created it), GitHub API v4, Shopify, Twitter, Airbnb, Pinterest — all complex product APIs where different clients need different data shapes.


gRPC: The Internal Services Protocol

gRPC (Google Remote Procedure Call) is a high-performance RPC framework built on HTTP/2 and Protocol Buffers. It's designed for service-to-service communication inside your backend — not for public APIs.

How gRPC Works

You define your API as a .proto file — a strongly-typed schema:

syntax = "proto3";

service UserService {
  rpc GetUser (UserRequest) returns (UserResponse);
  rpc CreateUser (CreateUserRequest) returns (UserResponse);
  rpc StreamUserEvents (UserRequest) returns (stream UserEvent);  // streaming!
}

message UserRequest {
  string user_id = 1;
}

message UserResponse {
  string id = 1;
  string name = 2;
  string email = 3;
  int64 created_at = 4;
}

From this .proto file, gRPC generates client and server code in any language — Go, Python, Java, C++, Node.js, Rust. The generated code handles serialization, network calls, and error handling automatically.

On the wire: Data is serialized as Protocol Buffers (protobuf) — a compact binary format. A JSON object that takes 200 bytes takes 30 bytes as protobuf. This is why gRPC is 3-10x more bandwidth-efficient than REST/JSON.

gRPC's 4 Communication Patterns

1. Unary RPC (like REST):
   Client sends one request → Server sends one response

2. Server Streaming:
   Client sends one request → Server streams many responses
   (e.g., "stream me all events since timestamp X")

3. Client Streaming:
   Client streams many requests → Server sends one response
   (e.g., upload a large file in chunks)

4. Bidirectional Streaming:
   Both client and server stream simultaneously
   (e.g., real-time collaborative editing, chat)

REST can only do Unary. gRPC does all four natively.

gRPC's Trade-offs

Advantages:

  • 3-10x smaller payload than JSON (protobuf binary vs verbose text)
  • Strong typing across languages — schema is the contract, code is generated
  • Bidirectional streaming built-in (HTTP/2 multiplexing)
  • Excellent for microservices — Uber uses gRPC for all internal service calls

Disadvantages:

  • Not human-readable — protobuf is binary, hard to debug with curl
  • Not browser-native — browsers can't call gRPC directly without gRPC-Web
  • Tight coupling — client and server must share .proto definitions
  • Overkill for simple, few services

Who uses it: Google (built it), Uber (all internal calls), Netflix, Square, Lyft. Any company with many microservices that need high-throughput, low-latency inter-service communication.


Choosing the Right API Style

┌─────────────────────────────────────────────────────────┐
│ Public-facing API (web/mobile clients)?                 │
│                                                         │
│  Simple CRUD, standard operations?          → REST      │
│  Complex data, many clients with different  │           │
│  data needs (mobile, web, partner APIs)?    → GraphQL   │
│                                                         │
│ Internal service-to-service communication?  → gRPC      │
│                                                         │
│ Mixed? Use all three:                                   │
│  External public API    → REST or GraphQL               │
│  Internal microservices → gRPC                          │
└─────────────────────────────────────────────────────────┘

Real architecture (Uber):

  • Mobile app → REST API Gateway → internal gRPC calls between services
  • Partner integrations → REST webhooks
  • Real-time ride tracking → WebSocket (neither REST nor gRPC)

API Gateway: The Front Door of Your Microservices

An API Gateway is a reverse proxy that sits at the entry point of your backend, handling cross-cutting concerns so individual services don't have to.

Clients
  │
  ▼
[API Gateway]
  ├── Authentication & Authorization
  ├── Rate Limiting
  ├── SSL Termination
  ├── Request Routing
  ├── Request/Response Transformation
  ├── Logging & Metrics
  ├── Circuit Breaking
  └── Caching
  │
  ├──► [User Service]
  ├──► [Order Service]
  ├──► [Payment Service]
  └──► [Notification Service]

Without an API Gateway, every microservice must implement auth, rate limiting, logging, and SSL themselves. That's N implementations of the same logic — duplicated, inconsistently, across every service.

With an API Gateway: implement once, enforce everywhere.

What API Gateways Handle

Routing:

/api/users/*    → User Service
/api/orders/*   → Order Service
/api/payments/* → Payment Service

Authentication:

Request arrives with JWT token
Gateway validates JWT (signature, expiry, claims)
If valid: add user_id header, forward to service
If invalid: return 401 immediately (service never sees the request)

Rate Limiting:

Tier: free → 100 req/min
Tier: pro  → 10,000 req/min
Tier: enterprise → unlimited

Gateway checks user's tier and request count in Redis
Exceeds limit → 429 Too Many Requests
Within limit → increment counter, forward request

Request Transformation:

Old client sends:  { "user_name": "Priya" }
New service expects: { "username": "Priya" }
Gateway transforms the request body in-flight

Real examples: AWS API Gateway, Kong (open source, Nginx-based), Nginx (with Lua scripting), Envoy, Traefik, Apigee (Google).


BFF Pattern: Backend for Frontend

A single API trying to serve a mobile app, a desktop web app, and third-party partners simultaneously has a fundamental problem: each client has radically different needs.

  • Mobile needs minimal data (battery, bandwidth)
  • Desktop needs rich data (big screen, fast connection)
  • Partner API needs different data shapes and authentication

BFF (Backend for Frontend) creates a dedicated API gateway per client type:

Mobile App     ──► [Mobile BFF]  ──► [Core Services]
Web App        ──► [Web BFF]     ──► [Core Services]
Partner API    ──► [Partner BFF] ──► [Core Services]

Each BFF is owned by the frontend team that uses it. The Mobile BFF team can optimize for mobile without worrying about breaking the Web BFF.

Who invented it: SoundCloud and Netflix were early adopters. Netflix runs dozens of BFFs — one per device type (TV, mobile, tablet, web, smart fridge).


API Versioning Strategies

APIs change. How you handle those changes determines whether you break your users.

Strategy 1: URL Versioning (Most Common)

/api/v1/users/123
/api/v2/users/123  ← new version with breaking changes

Simple. Explicit. Easy to route in API Gateway. The version is obvious in logs and browser history.
Downside: clutters URL space, clients must know which version to use.

Strategy 2: Header Versioning

GET /users/123
Accept: application/vnd.myapp.v2+json

Clean URLs. But less visible — harder to debug, can't test in browser directly.

Strategy 3: Query Parameter

GET /users/123?version=2

Easy to test. But versions in query params feel like an afterthought and break caching (same resource, different query).

Stripe's approach (timestamp-based versions):

Stripe-Version: 2023-10-16

Each API key is pinned to the version that existed when it was created. Changes never break existing integrations. New integrations get the latest version. Genius — and extremely expensive to maintain.

The rule: Never make breaking changes without a new version. A breaking change is: removing a field, changing a field's type, changing required fields, changing error formats.


Interview Scenario: REST vs GraphQL Trade-offs

Q: When would you use GraphQL over REST?

"I'd reach for GraphQL when I have multiple client types with meaningfully different data needs — like a mobile app that needs minimal data and a desktop app that needs the full dataset. The ability for clients to request exactly what they need eliminates over-fetching, which matters a lot on mobile.

I'd also choose GraphQL if the product is evolving fast and frontend teams need to iterate without waiting for backend API changes — they can just request new fields.

But I'd stick with REST when the API is simple and stable (few endpoints, consistent data shapes), when caching at the HTTP layer is important (CDN caching is trivial with REST, painful with GraphQL), or when the API is public and needs to be easily consumable without GraphQL client libraries.

For internal microservices, I'd use gRPC for both — REST and GraphQL carry too much HTTP overhead for high-throughput internal calls."


Key Takeaways

  • REST: Simple, cacheable, universal. Best for public APIs, CRUD operations, stable contracts.
  • GraphQL: Client-controlled queries, eliminates over/under-fetching. Best for complex products with many client types. Watch for N+1 and query cost.
  • gRPC: Binary protocol, streaming, strongly typed. Best for internal microservice communication. Not browser-native.
  • API Gateway centralizes auth, rate limiting, routing, logging — don't implement these in every service.
  • BFF pattern gives each client type a dedicated gateway optimized for its needs.
  • Versioning: URL versioning is most practical. Never make breaking changes without a version bump.
  • Most mature architectures use all three: GraphQL or REST externally, gRPC internally, API Gateway at the boundary.

Day 4 Complete

You've covered the full networking layer: Load Balancing (traffic distribution), CDNs (content delivery at the edge), and API Design (how clients talk to your system). These three topics are the entry points for every request that enters your architecture.

Tomorrow (Day 5) we go async — message queues, event-driven architecture, and the Saga pattern for distributed transactions. How systems communicate when they don't need an immediate answer, and why that changes everything about how you design for scale.



Tags: system-design api-design rest graphql grpc backend interview-prep