What is a GlobalFilter in Spring Cloud Gateway, and how does it differ from a GatewayFilter?
answer
- GlobalFilter = all routes, GatewayFilter = one route
- Same filter(exchange, chain) signature
- GatewayFilterAdapter wraps global into the combined chain
- Cross-cutting (auth/log/route) vs per-route transforms
- One sorted chain, not two
basics
~20 sA GlobalFilter runs on every route automatically. A GatewayFilter is configured per route. Both intercept the request/response; the difference is scope — global applies to all routes, gateway filters only to routes you attach them to.
solid answer
~40 sGlobalFilter is an interface (`Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)`) whose beans are applied to every matched route with no per-route configuration. GatewayFilter is the same shape but scoped to a single route, wired via `filters:` in config or the Java DSL (e.g. AddRequestHeader). Internally Gateway wraps each GlobalFilter in a GatewayFilterAdapter and merges it with that route's own GatewayFilters into one combined, sorted chain. So both coexist in the same chain — global ones are simply present on all routes. You reach for a GlobalFilter for cross-cutting concerns (auth, logging, metrics, tracing, the proxied call), and a GatewayFilter for behavior only some routes need.
code
java · 14 linesimport org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
@Component // a bean => applied to EVERY route
public class LoggingGlobalFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("--> " + exchange.getRequest().getURI());
return chain.filter(exchange); // delegate to the rest of the chain
}
}go deeper
Know global = every route, gateway = per route, and both intercept request/response.
Explain they're merged into one sorted chain via GatewayFilterAdapter.
Discuss the exchange attributes handoff and cost of global filters on all traffic.
Reason about where to place cross-cutting concerns and how to scope-guard a global filter without per-route config.
**Spring Cloud Gateway** is a reactive API gateway built on Spring WebFlux and Project Reactor. A request that matches a **Route** flows through a chain of filters before the gateway proxies it downstream and writes the response back. **GlobalFilter** is the interface: ```java public interface GlobalFilter { Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain); } ``` Any Spring bean implementing `GlobalFilter` is applied to **every** route the gateway serves — you never list it per route. This is where cross-cutting concerns live: authentication, request logging, correlation IDs, metrics, and the built-in routing filters (`NettyRoutingFilter`, `ForwardRoutingFilter`, `ReactiveLoadBalancerClientFilter`) that actually perform or prepare the proxied call. **GatewayFilter** is a similar interface but is attached to an individual route. You configure it declaratively: ```yaml spring: cloud: gateway: routes: - id: users uri: http://users-svc:8080 predicates: [Path=/users/**] filters: - AddRequestHeader=X-Tenant, acme ``` Here `AddRequestHeader` only affects the `users` route. **How they run together:** the `FilteringWebHandler` takes the route's GatewayFilters, then wraps every `GlobalFilter` bean in a `GatewayFilterAdapter` (an adapter that makes a GlobalFilter look like a GatewayFilter). It combines both lists and sorts the whole thing by `Ordered`/`@Order` using `AnnotationAwareOrderComparator`. The result is a single `DefaultGatewayFilterChain`. Thus at runtime there is no separate "global chain" vs "route chain" — it is one ordered list, and a global filter can be positioned before or after route filters purely by its order value. **ServerWebExchange** is the reactive request/response context passed to every filter; it carries the request, response, and a mutable attributes map (`exchange.getAttributes()`) that filters use to hand data to one another (e.g. the resolved downstream URL). **When to use which:** GlobalFilter for anything that must apply everywhere (security, observability, the routing mechanics). GatewayFilter for per-route transformations (header rewriting, path stripping, rate limiting on specific routes). **Gotcha:** because a GlobalFilter runs on *every* route, an expensive or blocking operation inside one hurts all traffic. Keep them non-blocking and cheap, and guard by predicate/attribute if you only care about some requests.
- How would you make a GlobalFilter effectively apply to only some routes?A GlobalFilter always runs on every route, so you guard inside it — check a request attribute, path, or a route-level attribute (e.g. via the route's metadata) and short-circuit with `chain.filter(exchange)` unchanged when it does not apply. If you truly need per-route scoping, use a GatewayFilter/GatewayFilterFactory instead.
- Do you have to annotate a GlobalFilter with @Component?You need it to be a Spring bean — @Component works, or a @Bean method in a @Configuration class. Any GlobalFilter bean is auto-discovered and added to the chain for all routes.
saying these in an interview costs you the question
- Claiming a GlobalFilter can be listed under a specific route's `filters:`
- Thinking global and route filters run in two separate chains
- Saying GlobalFilter and GatewayFilter have different method signatures