Spring AI Recipe: Migrating to Session Memory
Spring AI 2.1.0 gives conversational memory a fresh start, replacing the familiar ChatMemory API with a new session-based approach. Fortunately, bringing your existing applications along for the ride takes only a handful of changes.
One of the more significant changes in Spring AI 2.1.0 is a new approach to conversational memory. The Spring AI Session community project has been incorporated into Spring AI itself, bringing a new session-based memory model and marking the beginning of the end for the familiar ChatMemory API.
The existing ChatMemory API, along with its associated advisors and implementations, has been deprecated and is scheduled for removal in Spring AI 3.0.0. Although it will continue to work for now, there's no reason to wait until Spring AI 3.0.0 to make the switch.
Fortunately, migrating to session memory is surprisingly straightforward. In this recipe, we’ll take the original Chat Loop application and update it to use Spring AI’s new session memory support.
NOTE: We previously used the Spring AI Session community project in the Summarizing Chat Memory recipe, before it was incorporated into Spring AI itself. That recipe has since been updated to use the session memory support provided by Spring AI 2.1.0.
Starting with the Chat Loop
We’ll start with the code from the original Chat Loop recipe. That application uses MessageChatMemoryAdvisor and MessageWindowChatMemory to maintain conversational context between interactions with the model. Those types are now deprecated, so we’ll replace them with the new session memory implementation.
First, we need to upgrade the application to Spring AI 2.1.0. In build.gradle, change the springAiVersion property to:
ext {
set('springAiVersion', "2.1.0-RC2")
}Next, add two dependencies:
implementation 'org.springframework.ai:spring-ai-session-advisor'
implementation 'org.springframework.ai:spring-ai-autoconfigure-model-session'The first dependency provides the session advisor support, including types such as SessionAdvisors, SessionRepository, and SessionService. The second dependency provides auto-configuration for session memory, including the ability to automatically configure a SessionService.
But there’s one small catch: Before Spring AI can auto-configure a SessionService, it needs a SessionRepository.
Configuring a Session Repository
A SessionRepository is responsible for storing and retrieving session information. Spring AI provides two ready-made implementations:
InMemorySessionRepository— Stores session information in memory.JdbcSessionRepository— Stores session information in a relational database.
For this recipe, we’ll keep things simple and use InMemorySessionRepository. Perhaps we'll explore the JDBC-backed implementation in a future recipe.
All we need is a bean method that creates an InMemorySessionRepository:
@Bean
SessionRepository sessionRepository() {
return InMemorySessionRepository.builder().build();
}With a SessionRepository bean available, Spring AI's session auto-configuration can create the SessionService that we'll need in the next step.
One thing to keep in mind is that an in-memory repository is only suitable for applications where sessions don’t need to survive an application restart. For persistent session storage, you’ll want to consider the JDBC-backed implementation.
Configuring the Session Advisors
In the original Chat Loop application, we configured memory by applying a MessageChatMemoryAdvisor to the ChatClient.Builder. Now we’ll replace that configuration with one that uses session advisors.
Replace the existing chatMemoryCustomizer() bean method with:
@Bean
ChatClientBuilderCustomizer chatMemoryCustomizer(
SessionService sessionService) {
return builder -> builder
.defaultAdvisors(
SessionAdvisors.builder(sessionService).build());
}Notice that the method accepts a SessionService as a parameter. We don't need to explicitly create that service because Spring AI auto-configures it using the SessionRepository bean we declared earlier. The SessionAdvisors builder uses the service to configure the advisors responsible for integrating session memory with the ChatClient.
Get Craig Walls’s stories in your inbox
Join Medium for free to get updates from this writer.
By passing those advisors to defaultAdvisors(), we ensure that session memory is applied to every interaction with the chat client.
And with that, we’ve replaced the old chat memory configuration with the new session-based implementation.
Almost. There’s one more small change to make.
Identifying the Session
In the original Chat Loop application, each interaction with the model included the following advisor parameter:
.advisors(spec -> spec.param(
ChatMemory.CONVERSATION_ID, "DEMO"))This establishes a conversation ID that the old memory implementation uses to associate messages with a particular conversation. For simplicity, the conversation ID is hard-coded to "DEMO". In a real application, it would typically be associated with the currently authenticated user and, potentially, a specific conversation belonging to that user.
With session memory, we no longer use ChatMemory.CONVERSATION_ID. Instead, we identify the session using SessionAdvisors.session():
.advisors(SessionAdvisors.session("DEMO"))Conceptually, this is very similar to what we were doing before. The difference is that we’re now establishing a session ID rather than a conversation ID. And just as with the original conversation ID, a real application shouldn’t hard-code the session ID. But "DEMO" works perfectly well for this simple recipe.
That’s the last change we need to make!
Trying It Out
Now let’s fire up the application and see whether session memory works.
The easiest way to verify conversational memory is to tell the model something, then ask it to recall that information in a subsequent interaction.
Here’s an example:
How can I help?
> My favorite board game is Ticket to Ride.
- Got it! Ticket to Ride is your favorite board game.
What do you enjoy most about it?
> What did I say my favorite board game was?
- You said your favorite board game is Ticket to Ride.Success! The model remembers information from the earlier interaction, even though we didn’t repeat it in the second prompt. Without conversational memory, the model would have no way of knowing which board game we had mentioned previously.
The new session advisors handle the work of maintaining that context between interactions.
Wrapping Up
Spring AI 2.1.0 introduces a new session-based approach to conversational memory, replacing the ChatMemory API that we've used in previous recipes.
Although the old API will remain available until Spring AI 3.0.0, migrating to session memory now means we won’t have to worry about those deprecated types when the next major version arrives.
And as we’ve seen, the migration is remarkably simple. We only needed to add a couple of dependencies, declare a SessionRepository, replace the old memory advisor configuration, and switch from a conversation ID to a session ID.
That’s a small amount of work to bring an existing Spring AI application up to date with the new memory architecture.
Of course, session memory offers more possibilities than we’ve explored here. But for applications that simply need to maintain conversational context, these few changes are all it takes to get started.
Get the code for this and other Spring AI recipes at https://github.com/habuma/spring-ai-recipes.
If you’re exploring Spring AI, I’ve written a book (Spring AI in Action) that covers the core foundations — and I’ll continue sharing newer patterns like this here as the ecosystem evolves. You can find my book on the publisher’s website, at Amazon, or anywhere you buy technical books.









