Skip to content

Conversation

@Brack93
Copy link

@Brack93 Brack93 commented Dec 12, 2025

Background

Coroutines support for @Cacheable was introduced in 466c8d8 and refined in 6becfe2 (following Spring AOP coroutines support in c8169e5).

While this effectively solves long-lived cache use cases for suspend methods, it does not easily translate to request-scoped caching.

Although there is no direct support for standard methods as well, request-scoped caching is typically achieved by defining a @RequestScope CacheManager bean. However, since @RequestScope mechanism relies on thread local, the same approach is not suitable for coroutines, that can suspend and resume on different threads.

For a coroutine-based WebFlux server, a potential workaround involves explicitly adding to the request coroutine context the required resolved data (or a lazy resolver), using a custom coroutine context element, or manually passing it down the call stack as a method argument. However, this explicit approach strictly ties the implementation of a service - that may need this shared data at a deep request execution level - with the request context. It may also require a huge refactor to pass all the way down the required shared data, if the caching need emerges late in development. Additionally, for Kotlin WebFlux based GraphQL frameworks, clients can batch independent queries within the same request to save network resources, preventing an explicit design on server side that is able to cache common data for each possible queries combination.

For a better separation of concerns, we might prefer instead to inject the data provider as a service dependency, but still avoid duplicated executions within the same request.

Proposal

This PR provides request-scoped, proxy-based, cache management capability to Spring WebFlux servers leveraging Kotlin coroutines.

Specifically, suspend methods of Spring beans can now be annotated with @CoRequestCacheable.

class MyServiceBean {

	@CoRequestCacheable(key = "#userName")
	suspend fun fetchUserAgeFromDownstreamService(userName: String, authHeader: String): Int {
		// prepare request and fetch the user info
		return userInfo.age
	}

}

The cached result is tied to the web request coroutine context, ensuring that each new incoming web request triggers a new execution of the annotated method.

The required infrastructure can be enabled by using @EnableCoRequestCaching on a configuration class.

@Configuration
@EnableCoRequestCaching
class AppConfig {

	@Bean
	fun myService(): MyService {
		// configure and return a class having @CoRequestCacheable suspend methods
		return MyService()
	}

}

Although the proposed implementation could not fit in the already existing @Cacheable infrastructure, individual components have been reused or extended whenever possible to maintain consistency.

This commit provides request-scoped, proxy-based, cache management
capability to Spring WebFlux servers leveraging Kotlin coroutines.

Specifically, suspend methods of Spring beans can now be annotated
with @CoRequestCacheable. The cached result is tied to
the web request coroutine context, so each request will trigger
a new execution of the annotated method.

The required infrastructure can be enabled by using
@EnableCoRequestCaching on a configuration class.

Signed-off-by: Angelo Bracaglia <[email protected]>
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Dec 12, 2025
@Brack93 Brack93 marked this pull request as ready for review December 12, 2025 02:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: waiting-for-triage An issue we've not yet triaged or decided on

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants