Back to Blog
Guide7 min read2026-05-01

API Gateway Explained: Rate Limiting, Auth, and Routing

An API gateway sits in front of your services and handles cross-cutting concerns like rate limiting, authentication, and routing — here is how it works and when you need one.

What Is an API Gateway?

An API gateway is a server that acts as the single entry point for all client requests to your backend services. Instead of clients calling individual services directly, they call the gateway, which then routes requests to the appropriate service, enforces policies, and returns responses.

The gateway handles cross-cutting concerns — logic that would otherwise be duplicated across every service:

  • Authentication and authorization — validate tokens, check permissions
  • Rate limiting — protect services from abuse and overuse
  • Request routing — send requests to the right service based on path, headers, or query parameters
  • Request/response transformation — reshape payloads between clients and services
  • Logging and observability — centralized request logging, tracing, and metrics

When Do You Need an API Gateway?

Not every application needs a dedicated API gateway. A single monolith with built-in middleware handles most of these concerns internally. An API gateway becomes valuable when:

  • You have multiple services (microservices or serverless functions) behind a single API surface
  • You want to centralize authentication instead of implementing it in every service
  • You need rate limiting without modifying application code
  • You want to version your API and route traffic between versions

Rate Limiting: Protecting Your Services

Rate limiting prevents any single client from overwhelming your services. A simple token bucket algorithm — give each client N requests per window, replenish over time — handles most use cases.

Here is a rate limiter implemented as a PandaStack edge function:

// rateLimiter.js — Redis-backed rate limiting function
const redis = require('redis');

let client;
const getClient = () => {
  if (!client) {
    client = redis.createClient({ url: process.env.REDIS_URL });
    client.connect();
  }
  return client;
};

const main = async (params) => {
  const clientId = params.clientId || params.__ow_headers?.['x-client-id'];
  if (!clientId) {
    return { statusCode: 400, body: JSON.stringify({ error: 'clientId required' }) };
  }

  const redis = getClient();
  const key = `rate:${clientId}`;
  const limit = 100; // requests per window
  const window = 60;  // seconds

  const current = await redis.incr(key);
  if (current === 1) await redis.expire(key, window);

  if (current > limit) {
    return {
      statusCode: 429,
      body: JSON.stringify({ error: 'Rate limit exceeded', retryAfter: window })
    };
  }

  return {
    statusCode: 200,
    body: JSON.stringify({ allowed: true, remaining: limit - current })
  };
};

module.exports = { main };

PandaStack provides managed Redis as part of its database offering — use it as your rate limit store without running infrastructure.

Authentication at the Gateway Level

Validating JWTs at the gateway — before requests reach your services — keeps auth logic out of every service and creates a single enforcement point.

// authMiddleware.js — JWT validation edge function
const jwt = require('jsonwebtoken');

const main = (params) => {
  const authHeader = params.__ow_headers?.authorization;

  if (!authHeader?.startsWith('Bearer ')) {
    return { statusCode: 401, body: JSON.stringify({ error: 'Missing authorization header' }) };
  }

  const token = authHeader.slice(7);
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    return {
      statusCode: 200,
      body: JSON.stringify({ valid: true, userId: decoded.sub, roles: decoded.roles })
    };
  } catch (err) {
    return {
      statusCode: 401,
      body: JSON.stringify({ error: 'Invalid or expired token' })
    };
  }
};

module.exports = { main };

Request Routing Patterns

A gateway routes requests based on rules. Common patterns:

Path-based routing:

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

Header-based routing (API versioning):

  • Accept: application/vnd.api+json; version=1 → v1 service
  • Accept: application/vnd.api+json; version=2 → v2 service

Canary routing:

  • 10% of traffic → new service version
  • 90% of traffic → stable version

Building a Simple API Gateway with Edge Functions

PandaStack edge functions can serve as lightweight gateway components. Chain functions together: a rate limiter function, an auth function, and a routing function that proxies to the appropriate container service.

// gateway.js — simple routing gateway
const https = require('https');

const ROUTES = {
  '/users': process.env.USERS_SERVICE_URL,
  '/orders': process.env.ORDERS_SERVICE_URL
};

const proxy = (url, params) => new Promise((resolve) => {
  // proxy logic to upstream service
  resolve({ statusCode: 200, body: JSON.stringify({ proxied: true, to: url }) });
});

const main = async (params) => {
  const path = params.__ow_path || '/';
  const prefix = Object.keys(ROUTES).find(r => path.startsWith(r));

  if (!prefix) {
    return { statusCode: 404, body: JSON.stringify({ error: 'Route not found' }) };
  }

  return proxy(ROUTES[prefix], params);
};

module.exports = { main };

Gateway vs Service Mesh

A gateway handles north-south traffic (external clients to your services). A service mesh handles east-west traffic (service to service). Most teams need a gateway; only larger microservice architectures need both.

Conclusion

An API gateway is one of the highest-leverage infrastructure components you can add to a growing application. It centralizes authentication, protects services from abuse, and enables clean API versioning. PandaStack provides the edge functions, Redis, and container hosting you need to build one. Start at dashboard.pandastack.io and read more at docs.pandastack.io.

Ready to deploy?

Start free on PandaStack — no credit card required.

Start free on PandaStack

More in Guide

Browse all Guide articles →

See also