API Architecture

the complete guide to apis: rest, graphql, and websockets

nov 26, 2025 18 min read
Abstract representation of API connections and data flow

APIs (Application Programming Interfaces) are the invisible glue holding the modern web together. Every time you check the weather on your phone, send a tweet, or make an online payment, you're interacting with APIs. But not all APIs are created equal, and choosing the right architecture can make or break your application.

In this comprehensive guide, we'll explore the three dominant API paradigms: REST (the established standard), GraphQL (the flexible challenger), and WebSockets (the real-time specialist). You'll learn how each works, when to use them, and see practical code examples that you can implement today.


What is an API?

An API is a contract between two pieces of software, defining how they can communicate. Think of it as a menu at a restaurant: the menu tells you what dishes (data/functions) are available and how to order them (request format), but you don't need to know how the kitchen (server) prepares them.

In web development, APIs typically allow a client (like a mobile app or website) to request data from a server. The server processes the request and sends back a response, usually in JSON format.

A Simple API Example

Imagine you're building a weather app. Instead of collecting weather data yourself, you use a weather API:

GET https://api.weather.com/v1/current?city=London

Response:
{
  "temperature": 15,
  "conditions": "cloudy",
  "humidity": 72
}

REST: The Established Standard

REST (Representational State Transfer) is an architectural style introduced by Roy Fielding in 2000. It's not a protocol or standard, but a set of constraints that, when followed, create scalable and maintainable web services.

Core Principles of REST

1. Client-Server Architecture

The client and server are separate entities that communicate over HTTP. This separation allows them to evolve independently.

2. Statelessness

Each request from client to server must contain all the information needed to understand and process the request. The server doesn't store client context between requests.

3. Cacheability

Responses must define themselves as cacheable or non-cacheable to prevent clients from reusing stale data.

4. Uniform Interface

Resources are identified by URLs, and standard HTTP methods (GET, POST, PUT, DELETE) are used to manipulate them.

5. Layered System

The client can't tell whether it's connected directly to the end server or an intermediary (like a load balancer or cache).

HTTP Methods in REST

RESTful APIs use standard HTTP methods to perform CRUD (Create, Read, Update, Delete) operations:

Method Purpose Idempotent Example
GET Retrieve data Yes GET /users/123
POST Create new resource No POST /users
PUT Update/replace resource Yes PUT /users/123
PATCH Partial update No PATCH /users/123
DELETE Remove resource Yes DELETE /users/123

REST API Example

Let's build a simple REST API for managing blog posts. Here's how different operations would look:

Creating a Blog Post (POST)

POST /api/posts
Content-Type: application/json

{
  "title": "Understanding REST APIs",
  "content": "REST is an architectural style...",
  "author": "John Doe"
}

Response (201 Created):
{
  "id": 42,
  "title": "Understanding REST APIs",
  "content": "REST is an architectural style...",
  "author": "John Doe",
  "createdAt": "2025-11-26T10:30:00Z"
}

Retrieving All Posts (GET)

GET /api/posts?page=1&limit=10

Response (200 OK):
{
  "posts": [
    {
      "id": 42,
      "title": "Understanding REST APIs",
      "author": "John Doe"
    },
    {
      "id": 43,
      "title": "GraphQL vs REST",
      "author": "Jane Smith"
    }
  ],
  "total": 156,
  "page": 1
}

Updating a Post (PUT)

PUT /api/posts/42
Content-Type: application/json

{
  "title": "Understanding REST APIs - Updated",
  "content": "REST is an architectural style for distributed systems..."
}

Response (200 OK):
{
  "id": 42,
  "title": "Understanding REST APIs - Updated",
  "content": "REST is an architectural style for distributed systems...",
  "updatedAt": "2025-11-26T11:00:00Z"
}

Deleting a Post (DELETE)

DELETE /api/posts/42

Response (204 No Content)

REST Pros and Cons

Advantages

  • Simple and intuitive
  • Stateless (easy to scale)
  • Cacheable responses
  • Wide tooling support
  • Works with standard HTTP
  • Well-documented patterns

Disadvantages

  • Over-fetching (getting too much data)
  • Under-fetching (multiple requests needed)
  • Versioning challenges
  • No built-in real-time support
  • Can be chatty (many round trips)

GraphQL: The Flexible Alternative

GraphQL, developed by Facebook in 2012 and open-sourced in 2015, is a query language for APIs. Unlike REST, where the server defines what data is returned, GraphQL lets the client specify exactly what it needs.

How GraphQL Works

In GraphQL, you have a single endpoint (typically /graphql) that accepts queries. The client sends a query describing the data structure it wants, and the server responds with exactly that data—nothing more, nothing less.

GraphQL Query Example

Instead of multiple REST endpoints, you write a query:

query {
  user(id: "123") {
    name
    email
    posts {
      title
      createdAt
      comments {
        author
        text
      }
    }
  }
}

Response:
{
  "data": {
    "user": {
      "name": "John Doe",
      "email": "john@example.com",
      "posts": [
        {
          "title": "My First Post",
          "createdAt": "2025-11-20T10:00:00Z",
          "comments": [
            {
              "author": "Jane",
              "text": "Great post!"
            }
          ]
        }
      ]
    }
  }
}

Notice how the response structure exactly matches the query structure. This eliminates over-fetching and under-fetching.

GraphQL Mutations

While queries fetch data, mutations modify data. Here's how you'd create a blog post in GraphQL:

mutation {
  createPost(
    title: "Understanding GraphQL",
    content: "GraphQL is a query language...",
    authorId: "123"
  ) {
    id
    title
    createdAt
    author {
      name
    }
  }
}

Response:
{
  "data": {
    "createPost": {
      "id": "456",
      "title": "Understanding GraphQL",
      "createdAt": "2025-11-26T10:30:00Z",
      "author": {
        "name": "John Doe"
      }
    }
  }
}

GraphQL Schema

GraphQL APIs are strongly typed. You define a schema that describes all available types and operations:

type User {
  id: ID!
  name: String!
  email: String!
  posts: [Post!]!
}

type Post {
  id: ID!
  title: String!
  content: String!
  author: User!
  comments: [Comment!]!
  createdAt: DateTime!
}

type Comment {
  id: ID!
  text: String!
  author: String!
}

type Query {
  user(id: ID!): User
  posts(limit: Int, offset: Int): [Post!]!
}

type Mutation {
  createPost(title: String!, content: String!, authorId: ID!): Post!
  updatePost(id: ID!, title: String, content: String): Post!
  deletePost(id: ID!): Boolean!
}

GraphQL Pros and Cons

Advantages

  • No over-fetching or under-fetching
  • Single endpoint
  • Strongly typed schema
  • Excellent developer tools
  • Built-in documentation
  • Flexible queries

Disadvantages

  • Steeper learning curve
  • Caching is more complex
  • Can be overkill for simple APIs
  • Query complexity can impact performance
  • File uploads are non-standard

WebSockets: Real-Time Communication

Both REST and GraphQL follow a request-response model: the client asks, the server answers. But what if you need real-time, bidirectional communication? That's where WebSockets come in.

WebSockets provide a persistent, full-duplex connection between client and server. Once established, both sides can send messages at any time without the overhead of HTTP headers on every message.

How WebSockets Work

The WebSocket Handshake

1
Client Initiates

Client sends an HTTP request with an "Upgrade: websocket" header

2
Server Accepts

Server responds with "101 Switching Protocols" if it supports WebSockets

3
Connection Established

The HTTP connection is upgraded to a WebSocket connection

4
Bidirectional Communication

Both client and server can send messages at any time

WebSocket Code Example

Here's how you'd implement a simple WebSocket connection in JavaScript:

Client-Side (JavaScript)

// Create WebSocket connection
const socket = new WebSocket('wss://example.com/chat');

// Connection opened
socket.addEventListener('open', (event) => {
  console.log('Connected to server');
  socket.send(JSON.stringify({
    type: 'join',
    username: 'John'
  }));
});

// Listen for messages
socket.addEventListener('message', (event) => {
  const data = JSON.parse(event.data);
  console.log('Message from server:', data);
  
  if (data.type === 'chat') {
    displayMessage(data.username, data.message);
  }
});

// Send a message
function sendMessage(text) {
  socket.send(JSON.stringify({
    type: 'chat',
    message: text
  }));
}

// Connection closed
socket.addEventListener('close', (event) => {
  console.log('Disconnected from server');
});

// Error handling
socket.addEventListener('error', (error) => {
  console.error('WebSocket error:', error);
});

WebSocket Use Cases

Chat Applications

Real-time messaging where users need instant delivery of messages without polling.

Live Sports Scores

Push score updates to thousands of users simultaneously as events happen.

Collaborative Editing

Google Docs-style applications where multiple users edit the same document.

Financial Tickers

Stock prices and cryptocurrency values that update in real-time.

Gaming

Multiplayer games requiring low-latency, bidirectional communication.

IoT Dashboards

Real-time sensor data streaming from devices to monitoring dashboards.

WebSocket Pros and Cons

Advantages

  • True real-time communication
  • Bidirectional data flow
  • Low latency
  • Reduced overhead (no HTTP headers per message)
  • Server can push updates

Disadvantages

  • More complex to implement
  • Stateful (harder to scale)
  • No automatic reconnection
  • Firewall/proxy compatibility issues
  • Resource intensive (persistent connections)

Choosing the Right API Architecture

There's no one-size-fits-all answer. The best choice depends on your specific requirements:

Scenario Best Choice Why
Simple CRUD app REST Simple, well-understood, easy to cache
Mobile app with limited bandwidth GraphQL Fetch only needed data, reduce payload size
Chat application WebSockets Real-time, bidirectional communication
Complex data relationships GraphQL Flexible queries, avoid multiple requests
Public API for third parties REST Familiar, widely supported, good documentation
Live dashboard with updates WebSockets Server can push updates without polling
Microservices communication REST or gRPC Stateless, scalable, language-agnostic

Pro Tip: You Can Mix Them

Many modern applications use a combination. For example, you might use REST for most operations, GraphQL for complex data fetching on mobile apps, and WebSockets for real-time notifications. Choose the right tool for each job.

Tools to Help You Work with APIs

Working with APIs requires the right tools. Here are some from onlinetinker that can help:

Conclusion

APIs are the backbone of modern software development, enabling applications to communicate, share data, and build upon each other's capabilities. Understanding the differences between REST, GraphQL, and WebSockets empowers you to make informed architectural decisions.

REST remains the go-to choice for most applications due to its simplicity and wide support. GraphQL shines when you need flexible queries and want to minimize data transfer. WebSockets are essential for real-time, bidirectional communication.

The best developers don't dogmatically stick to one approach—they understand the strengths and weaknesses of each and choose the right tool for the job. As you build your next application, consider your specific requirements: Do you need real-time updates? Are you optimizing for mobile bandwidth? Is your data highly relational? Let these questions guide your choice.