Skip to content

list_sessions() performance degrades significantly with large session counts #4871

Closed

Description

@ferponse

Description

When using DatabaseSessionService.list_sessions() in an application with a growing number of sessions, the method becomes increasingly slow as there is no way to limit or paginate the returned results.

Impact

In our deployment (~5k sessions per app, PostgreSQL backend), list_sessions() takes ~40 seconds to return. This makes it impractical to use in any user-facing endpoint. As sessions accumulate over time, the problem only gets worse.

We initially assumed this was a database tuning issue on our side, but after profiling we confirmed the bottleneck is the unbounded SELECT — all rows are fetched and deserialized into Session objects regardless of how many the caller actually needs.

Expected behavior

list_sessions() should support some form of pagination (page_size / page_token or limit / offset) so that callers can retrieve sessions in manageable chunks. A sensible default (e.g. 20–50 results) would also prevent accidental full-table scans.

Current workaround

We've had to implement our own paginated query directly against the database, bypassing DatabaseSessionService entirely. This works but means we lose the benefits of the service abstraction and have to maintain our own serialization logic.

Related

This looks like the same issue reported in #4621. Adding my experience here as another data point — this is a real blocker for production use cases.

Environment

  • google-adk version: 1.27.1
  • Python: 3.11
  • Database: PostgreSQL (async via asyncpg)
  • Deployment: Kubernetes (GKE)

Activity

  1. added
    services[Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc
    on Mar 18, 2026
  2. added theissue type on Mar 18, 2026
  3. added a commit that references this issue on Mar 18, 2026
    8278123
  4. llalitkumarrr commented on Mar 20, 2026

    @llalitkumarrr
    Collaborator

    Hello @ferponse ,

    Thank you for raising this and for your contribution. We are reviewing it now and will merge it once all checks pass.

    Also I was looking at the your logic and had a quick question. It looks like it returns a default or specified number of pages but how would it work if a user wants to get the complete list? Would they have to check the total number of pages first?

    What are your thoughts on making this simpler? For example we could return the complete list by default and only limit the pages if the user specifically requests it.

  5. added a commit that references this issue on Mar 20, 2026
    076cae3
  6. ferponse commented on Mar 20, 2026

    @ferponse
    ContributorAuthor

    Hi @llalitkumarrr, great point — that makes total sense! I've updated the implementation in #4873:

    • Without page_size: list_sessions() returns the complete list, exactly as it does today. Fully backward compatible, no surprises for existing callers.
    • With page_size: pagination kicks in — results are limited and next_page_token is returned when there are more pages.

    This way users who need the full list don't have to iterate through pages, and users dealing with large datasets can opt in to pagination when they need it. Thanks for the feedback!

  7. ferponse commented on Mar 20, 2026

    @ferponse
    ContributorAuthor

    @llalitkumarrr I've also encapsulated the pagination parameters into a SessionPagination class for a cleaner API. Now it works like this:

    from google.adk.sessions.base_session_service import SessionPagination
    
    # No pagination — returns ALL sessions (default, fully backward compatible)
    response = await session_service.list_sessions(app_name="my_app", user_id="user")
    
    # With pagination — returns a page of 10
    response = await session_service.list_sessions(
        app_name="my_app",
        user_id="user",
        pagination=SessionPagination(page_size=10),
    )
    
    # Jump to a specific offset (e.g. skip first 20)
    response = await session_service.list_sessions(
        app_name="my_app",
        user_id="user",
        pagination=SessionPagination(page_size=10, page_offset=20),
    )
    
    # Iterate pages using next_page_token
    response = await session_service.list_sessions(
        app_name="my_app",
        user_id="user",
        pagination=SessionPagination(page_size=10, page_token=response.next_page_token),
    )

    All changes pushed to #4873. Let me know if you have any other feedback!

  8. sasha-gitg commented on Mar 22, 2026

    @sasha-gitg
    Collaborator

    closing in favor of: #4621

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

services[Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions