← Blog

Understanding API Gateways in Spring Boot Microservices

2026-09-08 · 6 min read · SubToAPI Team

When you're building a microservices system with Spring Boot, an API gateway is the single entry point that sits in front of all your services, routing incoming requests to the right backend, handling cross-cutting concerns like auth and rate limiting, and hiding your internal service topology from clients. In the Spring ecosystem, this is almost always implemented with Spring Cloud Gateway, a reactive, non-blocking library purpose-built for this job.

Without a gateway, every client — a mobile app, a frontend, a partner integration — would need to know the address of every individual microservice and reimplement things like authentication and retries on its own. That doesn't scale past two or three services. The gateway centralizes that logic once, in one deployable Spring Boot application, instead of duplicating it across dozens of clients.

Why Spring Boot Microservices Need a Gateway

A typical Spring Boot microservices architecture might have separate services for orders, users, payments, and inventory, each running on its own port, possibly scaled independently, possibly deployed on different nodes. Without a gateway:

The gateway solves this by exposing one public URL. Internally it forwards /api/orders/ to the orders service, /api/users/ to the users service, and so on, using service discovery (often Eureka or Kubernetes DNS) instead of hardcoded IPs.

How Spring Cloud Gateway Fits In

Spring Cloud Gateway is built on Spring WebFlux and Project Reactor, so it's asynchronous by design — it can hold thousands of in-flight requests without blocking threads, which matters when it's proxying traffic for your entire system. Routes are defined either in YAML or programmatically as Java beans.

A basic route definition in application.yml looks like this:

spring:
  cloud:
    gateway:
      routes:
        - id: orders-service
          uri: lb://ORDERS-SERVICE
          predicates:
            - Path=/api/orders/**
          filters:
            - StripPrefix=1
        - id: users-service
          uri: lb://USERS-SERVICE
          predicates:
            - Path=/api/users/**
          filters:
            - StripPrefix=1

Here, lb://ORDERS-SERVICE tells the gateway to resolve the actual host through client-side load balancing (via Eureka or another discovery client), so you never hardcode instance addresses. The StripPrefix=1 filter removes /api before forwarding, so the orders service just sees /orders/**.

You can achieve the same thing with a Java configuration if you prefer code over YAML:

@Bean
public RouteLocator customRoutes(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("orders-service", r -> r.path("/api/orders/**")
            .filters(f -> f.stripPrefix(1))
            .uri("lb://ORDERS-SERVICE"))
        .build();
}

What the Gateway Handles Beyond Routing

Routing is the baseline. In practice, a Spring Boot API gateway usually also handles:

A minimal custom filter that checks for a bearer token looks like this:

@Component
public class AuthFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String authHeader = exchange.getRequest().getHeaders().getFirst("Authorization");
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }
}

This is the same pattern used at the infrastructure level by dedicated API management platforms — the gateway checks credentials once, at the edge, so every service behind it can trust the request without re-validating it.

Gateway vs. Load Balancer vs. Service Mesh

These terms get conflated often enough that it's worth being precise:

In a typical Spring Boot setup, you'll have the gateway at the edge and possibly a mesh internally, but plenty of systems run fine with just the gateway.

Where an External API Fits Behind Your Gateway

Not every downstream your gateway routes to has to be a service you wrote. If one of your Spring Boot microservices needs to call an LLM — for a support-ticket classifier, a summarization endpoint, or an internal tool — it's common to put that call behind its own internal service rather than scattering API keys and HTTP clients across the codebase.

This is where a tool like SubToAPI is useful: it turns your existing Claude access into a clean HTTPS API with its own application keys (sub_live_...), streaming support, and usage metadata, so your microservice can call https://api.subtoapi.app/v1/messages the same way it would call any other internal REST dependency, and your gateway can apply the same auth and rate-limiting rules to that route as it does to everything else. Setup takes a few minutes — see the quickstart and the messages API reference if you want to wire it into a service behind your gateway. Streaming responses are documented separately at docs/streaming, and tool-use support at docs/tools.

Getting Started Practically

If you're adding a gateway to an existing Spring Boot microservices project:

  1. Add spring-cloud-starter-gateway as a dependency.
  2. Register services with a discovery client (Eureka, Consul, or your platform's native discovery).
  3. Define routes in YAML for a quick start, move to Java RouteLocator beans once you need conditional logic.
  4. Add a global filter for authentication before opening the gateway to real traffic.
  5. Add rate limiting and circuit breaking once you have real load patterns to tune against.

Don't try to make the gateway do too much business logic — its job is routing, security, and cross-cutting concerns, not domain logic that belongs in your services.

Questions

Is Spring Cloud Gateway the same as an API gateway? Spring Cloud Gateway is a specific implementation — a library you add to a Spring Boot application to build an API gateway. "API gateway" is the architectural pattern; Spring Cloud Gateway is one way to implement it in the Java/Spring ecosystem.

Do I need service discovery to use an API gateway in Spring Boot? No, you can hardcode uri values pointing to fixed hosts for simple setups. Service discovery (via lb://SERVICE-NAME) is recommended once you have multiple instances or services that move between hosts.

Can Spring Cloud Gateway replace Nginx? For internal service routing within a Spring Boot microservices system, yes, it often replaces Nginx entirely. Many teams still keep Nginx or a cloud load balancer in front for TLS termination and static asset serving, with the gateway handling application-level routing behind it.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →