skip to content

In Google ADK, what survives a restart with InMemorySessionService vs DatabaseSessionService?

level: juniorimportance: must knowfreq 72%

answer

  1. durability is a service choice, not a framework promise
  2. process memory versus a SQL row
  3. db_url and SQLAlchemy
  4. same session_id, new process
  5. temp: keys still evaporate

basics

~10 s

Nothing survives with InMemorySessionService — sessions, event history and state live in the process and vanish on restart. DatabaseSessionService writes them to a SQL database given by db_url, so the same session_id resumes afterwards.

solid answer

~40 s

A Google ADK `Session` holds three things: an id scoped to `(app_name, user_id)`, the ordered list of `Event` objects that make up the conversation, and a `state` dict. Which of those survive a restart is decided entirely by the `SessionService` you hand to the `Runner`. `InMemorySessionService` keeps everything in Python process memory — it is perfect for tests and `adk web` prototyping, and it loses every session the moment the process exits or the container is rescheduled. `DatabaseSessionService(db_url=...)` persists sessions, events and state through SQLAlchemy to SQLite, Postgres or MySQL, so `get_session(app_name, user_id, session_id)` returns the same conversation after a restart. `VertexAiSessionService` delegates storage to the managed Vertex AI service instead. The agent code does not change — only the service you construct.

code

python · 17 lines
python
from google.adk.agents import LlmAgent
from google.adk.runners import Runner
from google.adk.sessions import DatabaseSessionService

agent = LlmAgent(
    name="assistant",
    model="gemini-2.0-flash",
    instruction="Answer briefly.",
)

session_service = DatabaseSessionService(db_url="sqlite:///./adk_sessions.db")

runner = Runner(
    app_name="support_bot",
    agent=agent,
    session_service=session_service,
)

go deeper

for a junior

Be able to name the three session services and say plainly that the in-memory one loses everything when the process stops. Know that the service is passed to the Runner.

for a middle

Explain what a Session contains — id, events, state — and that only the service decides what is written down. Mention that DatabaseSessionService takes a SQLAlchemy db_url.

for a senior

Show that you would not ship an in-memory service behind more than one replica, and separate three guarantees: resumable threads, cross-session memory, and blob storage in an artifact service.

for a principal

Own the boundary between ADK's session store and your own system of record: what the framework's tables may hold, retention and deletion for user data, and whether a managed Vertex service or your own database is the right operational commitment.

## What a Session actually is In Google ADK, a `Session` is the record of one conversation thread. It carries an `id`, the `app_name` and `user_id` it belongs to, an `events` list, a `state` dictionary, and a `last_update_time`. The `events` list is the append-only history: every user message, model reply, function call and function response is stored as an `Event`. The `state` dict is the small key/value scratch space the agent and its tools read and write — order ids, preferences, flags. Together they are what "the agent remembers" within that thread. A `Session` object in your process is a snapshot. The thing that owns the durable copy is the `SessionService`, and it is a pluggable interface (`BaseSessionService`) with `create_session`, `get_session`, `list_sessions`, `delete_session` and `append_event`. In ADK's Python 2.x API these are coroutines, so you `await` them. ## The three implementations you actually choose between **`InMemorySessionService`** stores sessions in dictionaries inside the running Python process. Creating it takes no arguments and no infrastructure. It is what `InMemoryRunner` and the local `adk web` dev UI wire up by default. Its durability is exactly the lifetime of the process: kill the server, redeploy, or let a container be rescheduled, and every session, every event and every state key is gone. It is also per-process, so two replicas behind a load balancer do not see each other's sessions. **`DatabaseSessionService(db_url=...)`** takes a SQLAlchemy URL such as `sqlite:///./adk_sessions.db` or a Postgres DSN, creates its tables, and writes sessions, events and state rows there. Restarting the process changes nothing: `await session_service.get_session(app_name=..., user_id=..., session_id=...)` rehydrates the full event history and state. Because the store is external, several replicas share it, which is what makes horizontal scaling work at all. **`VertexAiSessionService`** hands storage to Google's managed service rather than a database you operate. You configure it with a project and location and it is the natural pairing when the agent is deployed to Vertex AI Agent Engine. ## The swap is a one-line change The important design property is that nothing in the agent, the tools or the runner loop is aware of which service is in use. You construct one and pass it to `Runner(app_name=..., agent=..., session_service=...)`. That is why the honest interview answer to "what survives a restart?" is "whichever service you configured" — the framework itself makes no promise. ## What still does not survive, whatever you pick Two carve-outs catch people out. First, state keys prefixed `temp:` are deliberately not persisted; they exist for the current invocation only and are dropped when the event is committed. Second, sessions and long-term memory are different subsystems: the `SessionService` persists *this thread*, while a `MemoryService` is what makes material from *past, completed sessions* searchable. Configuring a database-backed session service gives you resumable threads, not cross-session recall. Artifacts are a third store again. Binary blobs (an uploaded PDF, a generated chart) belong in an `ArtifactService`; `InMemoryArtifactService` is as volatile as its session counterpart, while `GcsArtifactService` puts the bytes in Cloud Storage. ## Practical guidance Use the in-memory service for unit tests and local iteration — it is fast and needs no fixture. Move to `DatabaseSessionService` the moment a human other than you talks to the agent twice, because "the bot forgot everything after the deploy" is indistinguishable from a bug to a user. Point it at SQLite for a single-process demo and at Postgres for anything real; SQLite over a network filesystem is not a substitute for a shared database. When you migrate, remember that the tables are ADK's schema, not yours: treat the session store as owned by the framework, and keep any business data you need to query yourself in your own tables, keyed by `user_id` and `session_id`. Session state is a conversation scratch pad, not a system of record.

  • If you move from InMemorySessionService to DatabaseSessionService, does any agent or tool code change?
    No. The `Runner` takes the service as a constructor argument and everything above it — agents, tools, the event loop — talks only to the `BaseSessionService` interface. You construct `DatabaseSessionService(db_url=...)` instead of `InMemorySessionService()` and pass it in. The one thing to plan for is operational: schema creation, connection pooling and backups now belong to you.
  • A user's preferences vanish when they start a new conversation even though you use DatabaseSessionService. Why?
    A persistent session service persists *each session*, and a new conversation is a new session id with its own state. Preferences that must follow the person need a `user:`-prefixed state key, which the service scopes to the `user_id` across all their sessions — or they need to live in your own database. Durability across restarts and durability across threads are two different guarantees.
  • Does DatabaseSessionService give the agent long-term memory of past conversations?
    Not by itself. It makes an old session retrievable if you know its id, but the agent does not search across sessions. Cross-session recall is the `MemoryService`'s job: completed sessions are ingested with `add_session_to_memory`, and the agent queries them through a memory tool. Session persistence and memory are separate services on the `Runner`.

saying these in an interview costs you the question

  • Claiming ADK persists sessions automatically without configuring a service
  • Thinking InMemorySessionService survives a container restart
  • Assuming a shared database means shared memory across sessions
  • Believing the agent code differs between session backends
  • Storing business records of truth in session state

context