Files
adk-python/contributing/samples/postgres_session_service
Hiroaki Sano 657acfadbb docs: Add PostgreSQL session storage sample and documentation
Merge https://github.com/google/adk-python/pull/3926

### Link to Issue or Description of Change

**1. Link to an existing issue (if applicable):**

- Related: #3916

**2. Or, if no issue exists, describe the change:**

**Problem:**
While `DatabaseSessionService` already supports PostgreSQL through SQLAlchemy, there is no documentation or sample code showing users how to configure and use it.

**Solution:**
Add a comprehensive sample under `contributing/samples/postgres_session_service/` that demonstrates:
- How to configure `DatabaseSessionService` with PostgreSQL
- The auto-generated database schema (sessions, events, app_states, user_states tables)
- Connection URL format and configuration options
- A working sample agent with session persistence

### Testing Plan

**Unit Tests:**

- [x] I have added or updated unit tests for my change.
- [x] All unit tests pass locally.

This is a documentation-only change (new sample), so no new unit tests are required. Existing tests continue to pass.

**Manual End-to-End (E2E) Tests:**

Tested locally with the following steps:

1. Started PostgreSQL using `docker compose up -d`
2. Set environment variables:

```bash
export POSTGRES_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/adk_sessions
export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)
export GOOGLE_CLOUD_LOCATION=us-central1
export GOOGLE_GENAI_USE_VERTEXAI=true
```
3. Ran `pip install google-adk asyncpg greenlet` to install the required packages
4. Ran `python main.py` - session created successfully
5. Ran `python main.py` again - previous session resumed with event history
6. Verified tables and rows created in PostgreSQL (sessions, events, app_states, user_states)

### Checklist

- [x] I have read the https://github.com/google/adk-python/blob/main/CONTRIBUTING.md document.
- [x] I have performed a self-review of my own code.
- [x] I have commented my code, particularly in hard-to-understand areas.
- [x] I have added tests that prove my fix is effective or that my feature works.
- [x] New and existing unit tests pass locally with my changes.
- [x] I have manually tested my changes end-to-end.
- [x] Any dependent changes have been merged and published in downstream modules.

### Additional context

This PR adds documentation and a working sample for an already-supported feature. The DatabaseSessionService class already handles PostgreSQL through its DynamicJSON type decorator which uses JSONB for PostgreSQL.

Files added:
- contributing/samples/postgres_session_service/README.md - Comprehensive guide
- contributing/samples/postgres_session_service/agent.py - Sample agent
- contributing/samples/postgres_session_service/main.py - Usage example
- contributing/samples/postgres_session_service/compose.yml - Local PostgreSQL setup
- contributing/samples/postgres_session_service/\_\_init\_\_.py - Package init

Co-authored-by: Liang Wu <wuliang@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3926 from hiroakis:feat-support-pg-for-conversation a5279d4fb2a63699f384c670928d77d882c25a25
PiperOrigin-RevId: 868816317
2026-02-11 13:25:52 -08:00
..

Using PostgreSQL with DatabaseSessionService

This sample demonstrates how to configure DatabaseSessionService to use PostgreSQL for persisting sessions, events, and state.

Overview

ADK's DatabaseSessionService supports multiple database backends through SQLAlchemy. This guide shows how to:

  • Set up PostgreSQL as the session storage backend
  • Configure async connections with asyncpg
  • Understand the auto-generated schema
  • Run the sample agent with persistent sessions

Prerequisites

  • PostgreSQL Database: A running PostgreSQL instance (local or cloud)
  • asyncpg: Async PostgreSQL driver for Python

Installation

Install the required Python packages:

pip install google-adk asyncpg greenlet

Database Schema

DatabaseSessionService automatically creates the following tables on first use:

sessions

Column Type Description
app_name VARCHAR(128) Application identifier (PK)
user_id VARCHAR(128) User identifier (PK)
id VARCHAR(128) Session UUID (PK)
state JSONB Session state as JSON
create_time TIMESTAMP Creation timestamp
update_time TIMESTAMP Last update timestamp

events

Column Type Description
id VARCHAR(256) Event UUID (PK)
app_name VARCHAR(128) Application identifier (PK)
user_id VARCHAR(128) User identifier (PK)
session_id VARCHAR(128) Session reference (PK, FK)
invocation_id VARCHAR(256) Invocation identifier
timestamp TIMESTAMP Event timestamp
event_data JSONB Event content as JSON

app_states

Column Type Description
app_name VARCHAR(128) Application identifier (PK)
state JSONB Application-level state
update_time TIMESTAMP Last update timestamp

user_states

Column Type Description
app_name VARCHAR(128) Application identifier (PK)
user_id VARCHAR(128) User identifier (PK)
state JSONB User-level state
update_time TIMESTAMP Last update timestamp

adk_internal_metadata

Column Type Description
key VARCHAR(128) Metadata key
value VARCHAR(256) Metadata value

Configuration

Connection URL Format

postgresql+asyncpg://username:password@host:port/database

Basic Usage

from google.adk.sessions.database_session_service import DatabaseSessionService
from google.adk.runners import Runner

# Initialize with PostgreSQL URL
session_service = DatabaseSessionService(
    "postgresql+asyncpg://postgres:postgres@localhost:5432/adk_sessions"
)

# Use with Runner
runner = Runner(
    app_name="my_app",
    agent=my_agent,
    session_service=session_service,
)

Advanced Configuration

Pass additional SQLAlchemy engine options:

session_service = DatabaseSessionService(
    "postgresql+asyncpg://postgres:postgres@localhost:5432/adk_sessions",
    pool_size=10,
    max_overflow=20,
    pool_timeout=30,
    pool_recycle=1800,
)

Running the Sample

1. Start PostgreSQL

Using Docker:

docker compose up -d

Or use an existing PostgreSQL instance.

2. Configure Connection

Create a .env file:

POSTGRES_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/adk_sessions
GOOGLE_CLOUD_PROJECT=<your-gcp-project-id>
GOOGLE_CLOUD_LOCATION=us-central1
GOOGLE_GENAI_USE_VERTEXAI=true

Or run export command.

export POSTGRES_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/adk_sessions
export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)
export GOOGLE_CLOUD_LOCATION=us-central1
export GOOGLE_GENAI_USE_VERTEXAI=true

3. Run the Agent

python main.py

Or use the ADK:

adk run .

Session Persistence

Sessions and events are persisted across application restarts:

# First run - creates a new session
session = await session_service.create_session(
    app_name="my_app",
    user_id="user1",
    session_id="persistent-session-123",
)

# Later run - retrieves the existing session
session = await session_service.get_session(
    app_name="my_app",
    user_id="user1",
    session_id="persistent-session-123",
)

State Management

PostgreSQL's JSONB type provides efficient storage for state data:

  • Session state: Stored in sessions.state
  • User state: Stored in user_states.state
  • App state: Stored in app_states.state

Production Considerations

  1. Connection Pooling: Use pool_size and max_overflow for high-traffic applications
  2. SSL/TLS: Always use encrypted connections in production
  3. Backups: Implement regular backup strategies for session data
  4. Indexing: The default schema includes primary key indexes; add additional indexes based on query patterns
  5. Monitoring: Monitor connection pool usage and query performance