Skip to main content

Google Cloud Firestore session storage backend for aiohttp-session

Project description

aiohttp-session-firestore

CI PyPI Python License

Google Cloud Firestore session storage backend for aiohttp-session.

Drop-in, async, server-side sessions — the cookie holds only an opaque key while all session data lives in Firestore.


Installation

pip install aiohttp-session-firestore

Quick start

from aiohttp import web
from aiohttp_session import setup, get_session
from google.cloud.firestore_v1 import AsyncClient

from aiohttp_session_firestore import FirestoreStorage

async def handler(request: web.Request) -> web.Response:
    session = await get_session(request)
    session["visits"] = session.get("visits", 0) + 1
    return web.Response(text=f"Visits: {session['visits']}")

def create_app() -> web.Application:
    app = web.Application()
    firestore_client = AsyncClient()
    storage = FirestoreStorage(firestore_client, max_age=86400)
    setup(app, storage)
    app.router.add_get("/", handler)
    return app

if __name__ == "__main__":
    web.run_app(create_app())

Configuration

FirestoreStorage accepts every parameter that aiohttp_session.AbstractStorage does, plus a few Firestore-specific ones:

Parameter Type Default Description
client AsyncClient (required) Firestore async client instance
collection_name str "aiohttp_sessions" Firestore collection for session documents
key_factory (() -> str) | None None Callable that produces new session keys. None uses Firestore auto-generated IDs.
cookie_name str "__session" Name of the HTTP cookie (compatible with Firebase Hosting)
max_age int | None None Session lifetime in seconds (None = browser session)
secure bool | None None Secure cookie flag — set to True in production
httponly bool True HttpOnly cookie flag
samesite str | None None SameSite cookie attribute ("Lax", "Strict", or "None")
domain str | None None Cookie domain
path str "/" Cookie path
encoder (object) -> str Firestore-aware json.dumps Session data encoder (handles DatetimeWithNanoseconds)
decoder (str) -> Any json.loads Session data decoder

Production recommendations

storage = FirestoreStorage(
    client,
    max_age=86400,       # 24-hour sessions
    secure=True,         # HTTPS only
    httponly=True,        # default — prevents JS access
    samesite="Lax",      # CSRF protection
)

Cookie name & Firebase Hosting

The default cookie name is __session. This is intentional: Firebase Hosting strips all cookies except one named __session before forwarding requests to Cloud Run, Cloud Functions, or any other backend. If you change cookie_name to anything else while deployed behind Firebase Hosting, the cookie will be silently dropped on every request and sessions will never persist.

If you are not behind Firebase Hosting (e.g. running directly on Cloud Run with a custom domain, GKE, or locally), you can safely use any cookie name:

storage = FirestoreStorage(client, cookie_name="MY_SESSION", ...)

Session expiration & Firestore TTL

When max_age is set, each session document is written with an expire field containing a UTC datetime. The library checks this field on every read and treats expired documents as missing immediately.

For automatic cleanup of expired documents, configure a Firestore TTL policy on the expire field:

gcloud firestore fields ttls update expire \
    --collection-group=aiohttp_sessions \
    --enable-ttl

Note: Firestore's TTL deletion is best-effort and may take up to 72 hours. The server-side expiration check in load_session ensures correctness regardless of TTL policy timing.

Document structure

Each session is stored as a Firestore document:

aiohttp_sessions/{firestore-auto-id}
├── data: '{"created": 1700000000, "session": {"user": "alice"}}'
└── expire: 2024-11-15T12:00:00Z   (only when max_age is set)

The data field contains a JSON-encoded string (controlled by the encoder/decoder parameters). The expire field is a native Firestore Timestamp, compatible with TTL policies.

Firestore costs

Each request that touches the session incurs:

Operation Firestore cost
Load (no cookie) 0 reads (short-circuits before Firestore call)
Load (cookie, doc exists) 1 document read
Load (cookie, doc missing) 1 document read
Save (non-empty session) 1 document write
Save (empty new session) 0 writes (skipped)
Save (empty existing session) 1 document delete

The library avoids unnecessary writes — new sessions that remain empty are never persisted.

Default encoder

The default encoder is a Firestore-aware json.dumps that automatically converts datetime objects (including Firestore's DatetimeWithNanoseconds) to millisecond Unix timestamps. This prevents serialization errors when session data contains values that originated from Firestore queries. To override, pass a custom encoder.

Limitations

  • Session data must be JSON-serializable (or serializable by your custom encoder). Avoid storing large blobs; Firestore documents are limited to 1 MiB.
  • Eventual consistency: Firestore in Datastore mode uses eventual consistency for some queries. This library reads by document ID (strongly consistent in both Native and Datastore mode).
  • No built-in encryption: Firestore encrypts data at rest (Google-managed keys). If you need app-level encryption, provide a custom encoder/decoder pair that encrypts before writing and decrypts after reading.
  • Sensitive data: Avoid storing secrets (passwords, tokens) in sessions. Sessions are intended for user state, not credential storage.

Development

# Clone and install dev dependencies
git clone https://github.com/dcgudeman/aiohttp-session-firestore.git
cd aiohttp-session-firestore
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

# Run checks
ruff check .
ruff format --check .
mypy aiohttp_session_firestore
pytest --cov

License

Apache 2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aiohttp_session_firestore-0.1.1.tar.gz (16.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aiohttp_session_firestore-0.1.1-py3-none-any.whl (10.9 kB view details)

Uploaded Python 3

File details

Details for the file aiohttp_session_firestore-0.1.1.tar.gz.

File metadata

File hashes

Hashes for aiohttp_session_firestore-0.1.1.tar.gz
Algorithm Hash digest
SHA256 2c99994c181a10297b79906811a66603bbec77a2e4f781c0e291e6399aa8134d
MD5 ee1a41ba4e3039debebf8b0617863578
BLAKE2b-256 e9024519f8557ce115ceee7b3ae37ef15b4e695a4d63a07ea28adad7af332107

See more details on using hashes here.

Provenance

The following attestation bundles were made for aiohttp_session_firestore-0.1.1.tar.gz:

Publisher: release.yml on dcgudeman/aiohttp-session-firestore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file aiohttp_session_firestore-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for aiohttp_session_firestore-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e28d023a450666e85b36b1211e4874f7f2fc7021350dc396f23aa1cebd3f7e10
MD5 6cd4ec0092107a9c004dae08c2cf2548
BLAKE2b-256 737c1f73f1024583a646e5cf1b48fb9598b44416f8e59b9952bc36d0cf3cb507

See more details on using hashes here.

Provenance

The following attestation bundles were made for aiohttp_session_firestore-0.1.1-py3-none-any.whl:

Publisher: release.yml on dcgudeman/aiohttp-session-firestore

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page