Filter order in spring-boot
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
In Spring Boot, filter execution order is controlled by the @Order annotation or by calling setOrder() on a FilterRegistrationBean. Filters with lower order values run first. When no order is specified, the execution sequence is undefined, which leads to subtle bugs when filters depend on each other. This article explains both ordering mechanisms, covers the interaction with Spring Security's filter chain, and provides concrete patterns for common filter configurations.
How Filter Ordering Works
Spring Boot builds a FilterChain that wraps all registered servlet filters. Each incoming HTTP request passes through every filter in the chain, in order. Each filter calls chain.doFilter(request, response) to pass control to the next filter. After the downstream filters and the servlet complete, control returns back through the chain in reverse order.
This means a filter can modify both the request (before calling chain.doFilter) and the response (after calling chain.doFilter).
Method 1: @Order Annotation
Apply @Order directly to a @Component filter class. Lower values execute first.
With this setup, every request hits logging first, then authentication, then rate limiting. If authentication fails, the rate limit filter never executes.
Method 2: FilterRegistrationBean
FilterRegistrationBean gives you more control. You can set the order, restrict the filter to specific URL patterns, and disable the filter without removing the class.
When using FilterRegistrationBean, do not annotate the filter class with @Component. If you do, Spring registers the filter twice: once through component scanning and once through the registration bean, which causes duplicate execution.
Preventing Double Registration
This is one of the most common Spring Boot filter mistakes. If your filter is annotated with @Component and you also register it with a FilterRegistrationBean, it runs twice per request.
To prevent this, either:
- Remove
@Componentfrom the filter class and use onlyFilterRegistrationBean. - Keep
@Componentbut disable the automatic registration by settingenabledtofalse:
Comparison of Ordering Approaches
| Approach | URL Pattern Control | Conditional Disable | Order Mechanism | Best For |
@Component + @Order | No (applies to all URLs) | No | Annotation value | Simple global filters |
FilterRegistrationBean | Yes (addUrlPatterns) | Yes (setEnabled) | setOrder() method | Route-specific or configurable filters |
Ordered interface | No | No | getOrder() method | Filters that need dynamic order values |
Interaction with Spring Security
Spring Security registers its own FilterChainProxy as a servlet filter with a default order of -100 (defined by SecurityProperties.DEFAULT_FILTER_ORDER). This means Spring Security's filter chain runs before most custom filters.
If you need a filter to run before Spring Security (for example, a CORS filter or a request ID generator), set its order below -100:
The Spring Security filter chain itself contains an ordered sequence of internal filters:
You can insert custom filters at specific points in this internal chain using HttpSecurity:
Common Filter Ordering Patterns
Recommended Order for a Typical API
Implementing a Request Timing Filter
This filter wraps chain.doFilter in a try/finally block so the timing is recorded even if a downstream filter or servlet throws an exception.
Debugging Filter Order
When filter order is not behaving as expected, enable Spring Boot's debug logging to see the registered filter chain:
You can also log the filter chain programmatically:
Common Pitfalls
- Not specifying an order at all. When multiple filters have no
@Orderannotation, their execution sequence is determined by class loading order, which is undefined and can change between builds. - Annotating a filter with both
@Componentand registering it withFilterRegistrationBean, causing it to execute twice per request. - Placing a CORS filter after Spring Security. The CORS preflight request (OPTIONS) is rejected by security before the CORS filter can add the required headers, resulting in opaque browser errors.
- Assuming
@Order(1)means "first." If Spring Security runs at order-100, any filter with a positive order runs after security. Use negative values for filters that must precede security. - Calling
chain.doFilter()after writing to the response. Once the response is committed (status and headers sent to the client), modifying headers in a downstream filter has no effect. - Using
@Orderon a@Beanmethod that returns aFilterRegistrationBean. The@Orderannotation on the bean method controls Spring bean initialization order, not filter execution order. Usebean.setOrder()instead.
Summary
- Filter execution order in Spring Boot is controlled by
@Orderannotations orFilterRegistrationBean.setOrder(). Lower values run first. - Use
@Component+@Orderfor simple global filters. UseFilterRegistrationBeanwhen you need URL pattern filtering or conditional registration. - Spring Security registers at order
-100. Filters that must run before security need a lower order value. - Avoid double registration by not combining
@ComponentwithFilterRegistrationBeanfor the same filter. - Always specify an explicit order on every filter. Relying on undefined default ordering causes intermittent bugs that are difficult to diagnose.
Related reading
- Final arguments in interface methods - what's the point?
- final keyword in method parameters
- Find a class somewhere inside dozens of JAR files?
- Find a private field with Reflection?
- Find Oracle JDBC driver in Maven repository
- Find where java class is loaded from
- Finding Key associated with max Value in a Java Map
- Finding Number of Cores in Java

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.