Skip to content

DatabaseSessionService.list_sessions lacks pagination support #4621

Open
stakeswky/adk-python
#1

Description

@rusherman

Description

DatabaseSessionService.list_sessions() queries all session rows for a given app_name (and optional user_id) without any pagination mechanism (LIMIT/OFFSET or cursor-based). When the number of sessions under an app grows large, this causes severe performance issues.

Impact

In our production environment with ~10k sessions per app, calling list_sessions() takes approximately 74 seconds to return, making the API endpoint essentially unusable.

Current Behavior

# base_session_service.py
class ListSessionsResponse(BaseModel):
    sessions: list[Session] = Field(default_factory=list)

async def list_sessions(
    self, *, app_name: str, user_id: Optional[str] = None
) -> ListSessionsResponse:
    ...

The method returns all sessions at once with no way to limit the result set.

Proposed Solution

Add pagination support to BaseSessionService.list_sessions() and DatabaseSessionService:

class ListSessionsResponse(BaseModel):
    sessions: list[Session] = Field(default_factory=list)
    next_page_token: str | None = None

async def list_sessions(
    self,
    *,
    app_name: str,
    user_id: str | None = None,
    page_size: int = 20,
    page_token: str | None = None,
) -> ListSessionsResponse:
    ...

The implementation should:

  • Accept page_size (with a reasonable default, e.g. 20, max 100) and page_token
  • Query with LIMIT/OFFSET (or cursor-based pagination)
  • Order by update_time DESC for consistent results
  • Return next_page_token when more results are available
  • Maintain backward compatibility (default behavior returns first page)

Workaround

We currently bypass DatabaseSessionService.list_sessions() by querying PostgreSQL directly with LIMIT/OFFSET in our service layer.

Environment

  • ADK version: 1.25.1
  • Python: 3.12
  • Database: PostgreSQL with asyncpg

Activity

  1. added
    services[Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc
    on Feb 25, 2026
  2. added theissue type on Feb 25, 2026
  3. added a commit that references this issue on Feb 25, 2026
    8019a2e
  4. klateefa commented on Feb 27, 2026

    @klateefa

    @rusherman
    Thank you for submitting this feature request. It’s currently under review by our team, and I’ll keep you posted on any updates. We appreciate your input!

  5. added
    needs review[Status] The PR/issue is awaiting review from the maintainer
    on Feb 27, 2026
  6. xuanyang15 commented on Feb 28, 2026

    @xuanyang15
    Collaborator

    @DeanChensj Could you please take a look?

  7. ecanlar commented on Mar 6, 2026

    @ecanlar
    Contributor

    I have the same problem.

  8. ecanlar commented on Mar 12, 2026

    @ecanlar
    Contributor

    Hi team! We're currently planning our next deployment cycle and were wondering if this pagination fix is likely to be merged soon. The current workaround of querying the DB directly isn't ideal for our long-term architecture. Do you have a rough ETA or a target version for this update? Appreciate the support!

  9. nightpool commented on Apr 22, 2026

    @nightpool

    @DeanChensj @xuanyang15 any update here?

  10. rialytics-software commented on Jul 24, 2026

    @rialytics-software

    Hi what is the status here? This was done pretty fast in adk-js. Also, same pagination required for events as well?

  11. jellevdberggg commented on Sep 15, 2026

    @jellevdberggg

    What is the status here? We're having a very slow sessions endpoint right now.

  12. inamdarmihir commented on Oct 29, 2026

    @inamdarmihir
    Contributor

    Opened #7799 for this. list_sessions gets optional page_size / page_token and the response an optional next_page_token; with neither passed, behavior is unchanged. It is keyset paging on the existing (last_update_time, user_id, id) order, so pages stay correct if sessions change between calls (adk-js uses offset paging, which skips or repeats rows in that case). The database and sqlite services push the cursor and LIMIT into SQL; Vertex AI, Redis, MongoDB and Firestore accept the same arguments but still slice client-side. The sessions endpoint takes the same query parameters and returns the next token in an X-Next-Page-Token header. It touches every backend because the base signature is shared, so I can split it if that's easier to review. I only ran the SQL path on sqlite.

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

Metadata

Metadata

Labels

needs review[Status] The PR/issue is awaiting review from the maintainerservices[Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions