"""Traefik reads answered from the index alone The rows page and the request chart read every raw row in the chosen range. With only (router_name, scraped_at) indexed, each of those rows was a heap fetch: a random disk read on a database whose indexes no longer fit in memory, which took the rows page to 12-28 s. Carrying the charted columns in the index makes these index-only scans; scraped_at gets an index of its own for the request chart, which filters on time across every router. Revision ID: traefik_004_covering_indexes Revises: traefik_003_access_log Create Date: 2026-10-08 """ from typing import Sequence, Union from alembic import op revision: str = "traefik_004_covering_indexes" down_revision: Union[str, None] = "traefik_003_access_log" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.drop_index("ix_traefik_metrics_router_scraped", "traefik_metrics") op.create_index("ix_traefik_metrics_router_scraped", "traefik_metrics", ["router_name", "scraped_at"], postgresql_include=["request_rate", "latency_p95_ms", "error_rate_5xx_pct"]) op.create_index("ix_traefik_metrics_scraped", "traefik_metrics", ["scraped_at"], postgresql_include=["request_rate", "error_rate_5xx_pct"]) def downgrade() -> None: op.drop_index("ix_traefik_metrics_scraped", "traefik_metrics") op.drop_index("ix_traefik_metrics_router_scraped", "traefik_metrics") op.create_index("ix_traefik_metrics_router_scraped", "traefik_metrics", ["router_name", "scraped_at"])