API Management Design

Contents:

3.1 API Gateway Pattern

API Gateway acts as the single entry point for all microservices, providing routing, security, and traffic management capabilities.

Concept and Importance

What is an API Gateway?

An API Gateway is a reverse proxy that functions as a single entry point for all requests from clients to microservices. It serves as a centralized “portal,” handling all requests and routing them to the appropriate service.

gateway

Why do we need an API Gateway?


Problems without an API Gateway:

┌─────────────────────────────────────────────────────────────┐
│                     Without API Gateway                     │
├─────────────────┬─────────────────┬─────────────────────────┤
│    Problem      │     Impact      │        Solution         │
├─────────────────┼─────────────────┼─────────────────────────┤
│ Client must know│ Complex client  │ Centralized through     │
│ many endpoints  │ implementation  │ Gateway                 │
├─────────────────┼─────────────────┼─────────────────────────┤
│ No centralized  │ Security risks  │ Centralized             │
│ security        │                 │ authentication          │
├─────────────────┼─────────────────┼─────────────────────────┤
│ Hard to monitor │ Difficult to    │ Centralized logging and │
│ and debug       │ debug/troublesh │ monitoring              │
└─────────────────┴─────────────────┴─────────────────────────┘

Real-world applications:

  • E-commerce platforms: Amazon, Shopify use API Gateway to manage hundreds of microservices
  • Banking systems: Used to secure and control API access
  • Social networks: Facebook, Twitter use it for rate limiting and analytics
  • IoT platforms: Manage millions of connected devices

3.2 gRPC Communication

gRPC enables high-performance communication between microservices using Protocol Buffers.

Concept and Why Use gRPC

What is gRPC?

gRPC (gRPC Remote Procedure Calls) is a high-performance, open-source RPC framework developed by Google. It uses HTTP/2 as the transport protocol and Protocol Buffers as the default serialization format.

gRPC

Why choose gRPC instead of REST?


Comparison gRPC vs REST:

┌────────────────────┬─────────────────┬─────────────────────────┐
│     Criteria       │       gRPC      │          REST           │
├────────────────────┼─────────────────┼─────────────────────────┤
│ Performance        │ High (Binary)   │ Medium (JSON)           │
│ Type Safety        │ Strong          │ Weak                    │
│ Streaming          │ Bi-directional  │ Not supported           │
│ Code Generation    │ Automatic       │ Manual                  │
│ Browser Support    │ Limited         │ Full                    │
│ Learning Curve     │ Steep           │ Easy                    │
│ Debugging          │ Harder          │ Easier                  │
└────────────────────┴─────────────────┴─────────────────────────┘

What problems does gRPC solve?

  1. High performance: Binary serialization is 5–10x faster than JSON
  2. Type safety: Compile-time checking reduces runtime errors
  3. Streaming: Supports real-time data streaming
  4. Multi-language: Code generation for 10+ languages
  5. Load balancing: Built-in client-side load balancing

Real-world applications:

  • Netflix: gRPC for internal microservices communication
  • Uber: gRPC for real-time location tracking and routing
  • Dropbox: File synchronization and metadata services
  • Square: Payment processing and financial transactions

Protocol Buffers Schema

Example gRPC API:

syntax = 'proto3';

package api;

message Order {
    string ID = 1;
    string customerID = 2;
    string Status = 3;
    repeated Item Items = 4;
    string PaymentLink = 5;
}

service OrderService {
    rpc CreateOrder(CreateOrderRequest) returns (Order);
    rpc GetOrder(GetOrderRequest) returns (Order);
    rpc UpdateOrder(Order) returns (Order);
}

Service Definition Structure

Proto file organization:

┌─────────────────────────────────────┐
│            micro.proto              │
├─────────────────────────────────────┤
│ Messages:                           │
│ ├── Order                           │
│ ├── OrderService                    │
│ ├── ItemsWithQuantity               │        
│ ├── Item                            │
│ ├── CreateOrderRequest              │
│ └── GetOrderRequest                 │
├─────────────────────────────────────┤
│ Services:                           │
│ ├── OrderService                    │
│ └── StockService                    │
└─────────────────────────────────────┘

gRPC Communication Flow

┌─────────────┐   CreateOrder()   ┌─────────────┐
│   Gateway   │─────────────────> │OrderService │
└─────────────┘                   └─────────────┘
       │                                │
       │        Order Response          │
       └────────────────────────────────┘

Service-to-service communication:

┌─────────────┐   CheckStock()   ┌─────────────┐
│OrderService │────────────────> │StockService │
└─────────────┘                  └─────────────┘
       │                                │
       │        Stock Response          │
       └────────────────────────────────┘

3.3 Asynchronous Messaging

Asynchronous messaging with RabbitMQ for event-driven architecture.

Concept and Why Use RabbitMQ

rabbitmq

What is RabbitMQ?

RabbitMQ is an open-source message broker that acts as a mediator between applications, allowing them to send and receive messages asynchronously. It implements AMQP (Advanced Message Queuing Protocol) and supports multiple messaging patterns.

Why choose RabbitMQ?

Problems with synchronous communication:

┌─────────────────────────────────────────────────────────────┐
│                Synchronous Communication Issues             │
├─────────────────┬─────────────────┬─────────────────────────┤
│    Problem      │     Impact      │   RabbitMQ Solution     │
├─────────────────┼─────────────────┼─────────────────────────┤
│ Tight Coupling  │ Cascading       │ Loose coupling via      │
│                 │ failures        │ queues                  │
├─────────────────┼─────────────────┼─────────────────────────┤
│ Blocking Calls  │ Poor            │ Asynchronous            │
│                 │ performance     │ processing              │
├─────────────────┼─────────────────┼─────────────────────────┤
│ No retry logic  │ Data loss       │ Persistent queues & DLQ │
└─────────────────┴─────────────────┴─────────────────────────┘

What problems does RabbitMQ solve?

  1. Decoupling: Producers and consumers work independently
  2. Reliability: Persistent messages and acknowledgments
  3. Scalability: Load balancing and clustering
  4. Flexibility: Multiple patterns (pub/sub, work queues, RPC)
  5. Fault tolerance: Dead Letter Queues and retry mechanisms

When to use RabbitMQ?

RabbitMQ Use Cases:

┌─────────────────┬─────────────────────┬───────────────────────┤
│     Pattern     │       Scenario      │        Example        │
├─────────────────┼─────────────────────┼───────────────────────┤
│ Work Queues     │ Task distribution   │ Image processing,     │
│                 │                     │ email sending         │
├─────────────────┼─────────────────────┼───────────────────────┤
│ Pub/Sub         │ Event broadcasting  │ Order created,        │
│                 │                     │ user registered       │
├─────────────────┼─────────────────────┼───────────────────────┤
│ RPC             │ Request/Response    │ Microservice          │
│                 │ communication       │ communication         │
└─────────────────┴─────────────────────┴───────────────────────┘

Real-world applications:

  • Instagram: Handles millions of photo uploads and notifications
  • Reddit: Comment processing and vote counting
  • Mozilla: Firefox update distribution

RabbitMQ Architecture

RabbitMQ Message Flow:

┌─────────────┐    Publish    ┌─────────────┐    Route    ┌─────────────┐
│  Producer   │─────────────> │  Exchange   │───────────> │    Queue    │
└─────────────┘               └─────────────┘             └─────────────┘
                                    │                          │
                                    |                          |
                                    │                          ▼
                             ┌─────────────┐            ┌─────────────┐
                             │   Binding   │            │  Consumer   │
                             └─────────────┘            └─────────────┘

Event Types and Exchange

const (
    OrderCreatedEvent = "order.created"  // Direct Exchange
    OrderPaidEvent    = "order.paid"     // Fanout Exchange
)
Types of Exchange:

┌─────────────────┐
│ Direct Exchange │  ← order.created (based on routing key)
├─────────────────┤
│ Fanout Exchange │  ← order.paid (broadcast to all) 
└─────────────────┘

Dead Letter Queue Implementation

DLQ Flow with Retry Mechanism:

┌─────────────┐    Processing  ┌─────────────┐
│ Main Queue  │──────────────> │  Consumer   │
└─────────────┘                └─────────────┘
       ▲                            │
       │                            ▼ (Failure)
       │ Retry (< 3)         ┌─────────────┐
       └─────────────────────│ Retry Logic │
                             └─────────────┘
                                    │
                                    ▼ (Exceeded retries)
                             ┌─────────────┐
                             │     DLQ     │
                             └─────────────┘

Message Retry Logic

func HandleRetry(ch *amqp.Channel, d *amqp.Delivery) error {
    retryCount := getRetryCount(d.Headers)
    retryCount++
    
    if retryCount >= MaxRetryCount {
        // Move to DLQ
        return sendToDLQ(ch, d)
    }
    
    // Exponential backoff
    time.Sleep(time.Second * time.Duration(retryCount))
    return republish(ch, d, retryCount)
}