Free Ebook cover API Gateways for Beginners: Managing, Securing, and Scaling Web APIs

API Gateways for Beginners: Managing, Securing, and Scaling Web APIs

New course

12 pages

Gateway Request Routing: Paths, Methods, Hosts, and Backends

Capítulo 2

Estimated reading time: 8 minutes

+ Exercise

Routing Is the Gateway’s Core Job

Request routing is the process of deciding where an incoming HTTP request should go. An API gateway receives a request (for example, GET https://api.example.com/users/123), matches it against a set of routing rules, and forwards it to the correct backend (also called an upstream), such as a monolith, a microservice, or a serverless function.

A route rule typically matches on one or more of these attributes:

  • Host (domain): api.example.com vs admin.example.com
  • Path: /users/123, /orders/987
  • HTTP method: GET, POST, PUT, DELETE
  • Other constraints (optional): headers, query params, client IP, etc. (not required for basic routing)

Once a route matches, the gateway selects an upstream target (one instance or one function), optionally rewrites the URL, and proxies the request.

Route Matching: Host-Based and Path-Based

Host-based routing

Host-based routing uses the request’s Host header (or SNI for TLS) to choose a backend. This is common when you want different subdomains to map to different systems.

  • api.example.com → public API gateway routes
  • admin.example.com → admin backend
  • partner.example.com → partner API backend

Host-based routing is often the first split because it cleanly separates traffic domains and can reduce accidental overlap between routes.

Continue in our app.

You can listen to the audiobook with the screen off, receive a free certificate for this course, and also have access to 5,000 other free online courses.

Or continue reading below...
Download App

Download the app

Path-based routing

Path-based routing matches the URL path (everything after the domain). Gateways usually support patterns such as:

  • Exact match: /users
  • Prefix match: /users/ matches /users/123, /users/profile
  • Wildcard/glob: /api/*
  • Path parameters: /users/{id} or /users/:id

In practice, prefix matching is the most common for service routing (for example, everything under /users/ goes to the user service).

HTTP Method Constraints (GET vs POST, etc.)

Two routes can share the same path pattern but differ by HTTP method. Method constraints help you:

  • Send reads and writes to different backends (rare, but possible).
  • Apply different policies per method (for example, stricter limits on POST).
  • Avoid accidental matches (for example, only allow GET on a read-only endpoint).

Example: same path, different method handling:

  • GET /orders/{id} → order service (read handler)
  • DELETE /orders/{id} → order service (admin-only handler)

If a request matches the host and path but not the method, the gateway should treat it as “no route” (often returning 404 or 405 Method Not Allowed, depending on gateway behavior and configuration).

Priority and Ordering Rules (Why Some Routes “Win”)

When multiple routes could match the same request, the gateway needs a deterministic way to choose one. Most gateways use a combination of:

  • Specificity: exact paths beat prefixes; longer prefixes beat shorter prefixes.
  • Explicit priority: a numeric priority you set (higher wins).
  • Declaration order: first match wins (common in simpler systems).

Consider these routes:

  • Route A: /users/ (prefix)
  • Route B: /users/admin/ (prefix)

A request to /users/admin/settings should match Route B, because it is more specific (longer prefix). If your gateway uses “first match wins,” you must place Route B before Route A, or assign Route B a higher priority.

Practical rule: define the most specific routes first (or with highest priority), then broader catch-all routes last (like /api/*).

Mapping Public Endpoints to Upstream Services

Routing is not only about matching; it’s also about mapping. The gateway often exposes a stable public API surface while your internal services can have different hostnames, ports, and path structures.

Common routing patterns

  • Monolith catch-all: /api/* → monolith upstream
  • Service split: /users/* → user service, /orders/* → order service
  • Serverless: /webhooks/* → function per event type

Example target mapping (conceptual):

Public:  https://api.example.com/users/*   -> Upstream: http://users-service:8080/*  (cluster internal DNS)Public:  https://api.example.com/orders/*  -> Upstream: http://orders-service:8080/*Public:  https://api.example.com/api/*     -> Upstream: http://monolith:8080/*

Step-by-Step: Build a Simple Route Table

This step-by-step approach helps you design routes without surprises.

Step 1: List your public API surface

  • GET /users/{id}
  • POST /users
  • GET /orders/{id}
  • POST /orders
  • GET /api/status (legacy monolith)

Step 2: Decide the host strategy

Start simple with one host:

  • api.example.com for all public endpoints

If you need separation later, you can introduce additional hosts (for example, admin.example.com).

Step 3: Create path prefixes per backend

  • /users/ → user service
  • /orders/ → order service
  • /api/ → monolith

Step 4: Add method constraints where needed

For example, if the user service only supports GET and POST on certain endpoints, constrain the route to those methods to avoid forwarding unsupported methods.

Step 5: Set priority/ordering

Place more specific routes first. For example, if you have a special admin endpoint under users:

  • /users/admin/ (higher priority)
  • /users/ (lower priority)

URL Rewriting and Path Parameter Forwarding

Gateways often need to rewrite URLs because the public API path structure may not match the internal service’s routes. Two common needs are:

  • Strip a prefix before forwarding.
  • Preserve and forward path parameters (like {id}).

Prefix stripping (rewrite)

Suppose your public API is /users/*, but the user service expects routes without the /users prefix (for example, it expects /v1/{id} or just /{id}).

Example rewrite: strip /users and forward the rest:

Incoming:  GET /users/123Forward to: http://users-service:8080/123

Or rewrite to a versioned internal path:

Incoming:  GET /users/123Forward to: http://users-service:8080/v1/users/123

Path parameters forwarding

With a parameterized route like /orders/{orderId}, the gateway matches the pattern and captures orderId. Most gateways forward the full path by default, so the backend receives /orders/987 unchanged. If you rewrite, ensure the parameter is preserved in the rewritten path.

Route match: /orders/{orderId}Incoming:    GET /orders/987Rewrite to:  /v2/orders/987Forward to:  http://orders-service:8080/v2/orders/987

Practical check: verify that your backend framework’s route template matches what it will actually receive after gateway rewriting.

Basic Load Balancing Across Multiple Upstream Instances

In production, a “backend” is usually a pool of instances (multiple pods/VMs/containers) rather than a single server. The gateway can load balance across them to improve throughput and availability.

Common load balancing strategies

  • Round-robin: send requests to each instance in turn.
  • Least connections: prefer the instance with fewer active connections.
  • Random: simple distribution, sometimes good enough.
  • Hash-based (sticky-ish): choose instance based on a key (client IP, header, cookie) to improve cache locality or session affinity.

Example upstream pool for the user service:

users-service upstream pool: - http://10.0.1.10:8080 - http://10.0.1.11:8080 - http://10.0.1.12:8080Strategy: round-robin

When the route /users/* matches, the gateway picks one healthy instance from the pool and forwards the request.

Health Checks (Conceptual) and Why They Matter for Routing

Health checks help the gateway avoid sending traffic to broken instances. Conceptually, the gateway maintains a list of upstream targets and marks them healthy/unhealthy based on checks.

Types of health checks

  • Active checks: the gateway periodically calls a health endpoint (for example, GET /health) on each instance.
  • Passive checks: the gateway infers health from real traffic failures (timeouts, connection errors, repeated 5xx responses).

Typical behavior: if an instance fails health checks, it is temporarily removed from the load balancing rotation. When it recovers, it is added back.

Practical tip: ensure each service exposes a lightweight health endpoint that does not depend on slow downstream calls unless you intentionally want to reflect dependency health.

Putting It Together: A Practical Routing Layout

The following layout demonstrates the requested patterns: a monolith catch-all, two microservices, and serverless routing.

Example route set (conceptual)

Host: api.example.com1) Path: /users/*   Methods: GET, POST, PUT, DELETE   Upstream: users-service pool   Rewrite: strip /users (optional)2) Path: /orders/*  Methods: GET, POST, PUT, DELETE   Upstream: orders-service pool   Rewrite: strip /orders (optional)3) Path: /api/*     Methods: ANY   Upstream: monolith pool   Rewrite: none4) Path: /functions/user-created   Methods: POST   Upstream: serverless function invoke endpoint   Rewrite: map to provider-specific invoke path

Pattern: /api/* to a monolith

This is useful when you are migrating gradually. You can keep legacy endpoints under /api/ while moving new domains (users, orders) to dedicated services.

Incoming:  GET /api/statusForward to: http://monolith:8080/api/status

Pattern: /users/* to a user service

All user-related endpoints route to the user service. If the user service is versioned internally, rewrite accordingly.

Incoming:  POST /usersForward to: http://users-service:8080/v1/users

Pattern: /orders/* to an order service

All order-related endpoints route to the order service, with path parameters preserved.

Incoming:  GET /orders/987Forward to: http://orders-service:8080/v1/orders/987

Pattern: routing to serverless functions

Gateways can route certain endpoints to serverless functions, often for event handlers, webhooks, or lightweight glue logic. The gateway still matches host/path/method, then forwards to a function invocation endpoint (which may be HTTP-based or provider-specific).

Incoming:  POST /functions/user-createdGateway action: invoke function user-createdForward to: serverless invoke URL (provider-specific)Body/headers: forwarded (possibly with added auth headers)

Practical tip: keep serverless routes narrow and explicit (exact paths and strict methods) to avoid accidental invocation from broad wildcard routes.

Now answer the exercise about the content:

In an API gateway, why should more specific routes like /users/admin/ be placed before broader routes like /users/ (or given higher priority)?

You are right! Congratulations, now go to the next page

You missed! Try again.

When routes overlap, gateways resolve matches deterministically (often by specificity, configured priority, or first-match order). Defining the most specific route first (or highest priority) ensures it matches instead of a broader prefix route.

Next chapter

Authentication at the Gateway: API Keys, JWT, and OAuth2 Basics

Arrow Right Icon
Download the app to earn free Certification and listen to the courses in the background, even with the screen off.