Release Readiness Checklist
Use this checklist before full rollout (100%) or production freeze approval.
Scope
- Serving API (
/v2/homepage,/v2/homepage/refresh) - Retrieval/ranking pipelines
- Feature and personalization runtime dependencies
One-Command Gate Runner
Run the default release checks with:
uv run python scripts/release_readiness.py
Run with full test suite:
uv run python scripts/release_readiness.py --with-full-tests
Run Feast v2 release gates:
uv run python scripts/release_readiness.py --with-feature-store-v2-gates
Run Feast v2 rollout gates with capacity evidence from deployment variables and a time-based recommendation-quality artifact:
uv run python scripts/release_readiness.py \
--only-feature-store-v2-gates \
--feature-store-v2-capacity-from-env \
--recommendation-quality-artifact artifacts/recommendation_quality/time/latest_vs_production.json \
--recommendation-quality-candidate-model latest \
--recommendation-quality-baseline production \
--recommendation-quality-split time \
--recommendation-quality-k 10 \
--recommendation-results-artifact artifacts/recommendation_quality/served_results.jsonl
Run staging serving API v2 gates after deployment:
uv run python scripts/release_readiness.py \
--skip-default-checks \
--serving-api-base-url http://<staging-hh-lion-service> \
--serving-api-member-user-id <known-featured-member-id> \
--serving-api-load-requests 50 \
--serving-api-load-concurrency 5
Run with canary metrics guardrail snapshot:
uv run python scripts/release_readiness.py --metrics-snapshot <path-to-metrics.json>
Run one-command readiness with live Prometheus collection:
uv run python scripts/release_readiness.py \
--prometheus-url http://<prometheus-host>:9090 \
--metrics-output artifacts/release/canary-metrics.json
Generate snapshot directly from Prometheus canary queries:
uv run python scripts/export_canary_metrics_snapshot.py \
--prometheus-url http://<prometheus-host>:9090 \
--output artifacts/release/canary-metrics.json
Accepted snapshot formats:
{
"homepage_p95_latency_seconds": 0.82,
"homepage_fallback_ratio": 0.06
}
{
"collected_at": "2026-02-18T10:30:00Z",
"metrics": {
"homepage_p95_latency_seconds": 0.82,
"homepage_fallback_ratio": 0.06
}
}
Quality Gates
- Static checks:
uv run ruff check .uv run mypy recsys
- Contract/integration tests pass for:
- API contracts:
uv run pytest --no-cov tests/contract/test_homepage_api.py - model signature contracts:
uv run pytest --no-cov tests/contract/test_model_signatures.py - model promotion gates:
uv run pytest --no-cov tests/unit/test_register_model_gates.py - alert/runbook linkage + guardrail threshold alignment checks:
uv run pytest --no-cov tests/unit/test_prometheus_alert_runbooks.py - Grafana dashboard config sync:
uv run pytest --no-cov tests/unit/test_grafana_dashboard_configmap.py - test spec hygiene (no stale bootstrap placeholders):
uv run pytest --no-cov tests/unit/test_test_spec_hygiene.py - release readiness metric snapshot parsing/guardrails:
uv run pytest --no-cov tests/unit/test_release_readiness.py - canary metrics snapshot exporter script:
uv run pytest --no-cov tests/unit/test_export_canary_metrics_snapshot.py - CatBoost ranker business metrics exporter script:
uv run pytest --no-cov tests/unit/test_export_catboost_ranker_business_metrics_snapshot.py
- API contracts:
- No
/v1routes are registered:uv run pytest --no-cov tests/integration/test_api_endpoints.py::TestRouteVersioning::test_no_v1_routes_are_registered
- Core
/v2integration paths pass:- readiness failure-mode:
uv run pytest --no-cov tests/integration/test_api_endpoints.py::TestHealthEndpoint::test_readiness_returns_503_when_personalization_queue_unhealthy - API error security behavior:
uv run pytest --no-cov tests/integration/test_api_endpoints.py::TestErrorHandling - guest cohort path:
uv run pytest --no-cov tests/integration/test_guest_cohort.py - established member path:
uv run pytest --no-cov tests/integration/test_established_member.py - progressive enhancement path:
uv run pytest --no-cov tests/integration/test_progressive_enhancement.py - refresh ownership isolation:
uv run pytest --no-cov tests/integration/test_refresh_ownership.py
- readiness failure-mode:
Business Override Removal Rollout
- Confirm no application producers, Kafka fixtures, or API clients emit
section_type=business_override. - Treat
scripts/migrations/026_remove_business_override_section_type.sqlas a manual ClickHouse operation. Count affected production rows first, run the cleanup mutation during a maintenance window, monitorsystem.mutations, then apply the enum narrowing after cleanup succeeds. - Communicate the intentional interaction-event Avro enum break to downstream consumers before schemas generated from this branch are promoted.
Feast V2 Gates
- Static Feast contracts pass:
uv run pytest --no-cov tests/contract/test_clickhouse_feature_store_v2_schema.py tests/contract/test_feast_repo_v2.py
- Feast v2 unit and workflow guardrails pass:
uv run pytest --no-cov tests/unit/test_feature_store_contracts_v2.py tests/unit/test_feature_store_config.py tests/unit/test_feature_store_clients.py tests/unit/test_feature_store_publisher.py tests/unit/test_feature_store_health_v2.py tests/unit/test_feature_quality_checks_v2.py tests/unit/test_feature_store_store.py tests/unit/test_feature_jobs_v2.py tests/unit/test_feature_store_v2_operations.py tests/unit/test_validate_feature_store_v2.py
- Feast v2 integration tests pass with Docker-backed ClickHouse/Redis or production-like local services:
uv run pytest --no-cov -m "integration and feature_store_v2" -q
- Feast v2 performance regression tests and benchmark smoke gates pass:
uv run pytest --no-cov tests/performance/test_feature_store_online_v2.py tests/performance/test_feature_store_offline_v2.py -m performance -quv run python scripts/benchmark_feature_store_v2.py --iterations 30 --offline-rows 50000 --publication-rows 10000 --fail-on-regression --output text
- Capacity validation runs with explicit production-like inputs:
uv run python scripts/release_readiness.py --skip-default-checks --feature-store-v2-capacity-from-env
- Recommendation-quality validation runs against the time-based production baseline artifact:
uv run python scripts/release_readiness.py --skip-default-checks --recommendation-quality-artifact artifacts/recommendation_quality/time/latest_vs_production.json --recommendation-quality-candidate-model latest --recommendation-quality-baseline production --recommendation-quality-split time --recommendation-quality-k 10
- Served result validation enforces zero duplicate, invalid, unavailable, and untraceable exposures:
uv run python scripts/release_readiness.py --skip-default-checks --recommendation-results-artifact artifacts/recommendation_quality/served_results.jsonl
- CatBoost ranker rollout expansion requires live business-metric evidence from the canary/A/B window:
uv run python scripts/export_catboost_ranker_business_metrics_snapshot.py --output artifacts/release/ranker-business-metrics.jsonuv run python scripts/release_readiness.py --skip-default-checks --catboost-ranker-business-metrics-snapshot artifacts/release/ranker-business-metrics.json- for manual deploy/release workflows that expand CatBoost ranker traffic, set
require_catboost_ranker_business_metrics=trueand providecatboost_ranker_business_metrics_snapshot=artifacts/release/ranker-business-metrics.json; the workflow fails before build/release if the required snapshot path is omitted - for
promote-production-modelruns where the resolved candidate is a CatBoost ranker by model name, model-version tag, or source-run tag, providecatboost_ranker_business_metrics_snapshot=artifacts/release/ranker-business-metrics.json; production promotion fails before alias movement if the snapshot path is omitted or the gate fails - defaults require at least 1,000 top-slot impressions and 1,000 requests per variant, at least 10 successes and 10 failures per variant for each CTR/CVR confidence calculation,
>= 0.001absolute point lift on top-slot CTR and booking CVR versus baseline, a positive 95% lower-confidence-bound lift for both metrics, and>= 0.95of candidate requests served by known CatBoost strategy IDs - tune
--catboost-ranker-min-online-z-scoreonly with experiment-owner approval; the default1.96is the normal-approximation multiplier for a 95% confidence interval - CatBoost registry promotion also requires non-negative 95% lower-confidence-bound offline lift for NDCG, request-level top-slot click-rate, and request-level top-slot booking-rate proxy metrics; it requires bounded model and baseline NDCG@10, MAP@10, MRR@10, and recall@10 payloads plus bounded deltas, and rejects impossible rates/deltas, inconsistent holdout counts, and sparse or rate-inconsistent top-slot success/failure counts, so do not promote runs that only have positive point-estimate deltas
- by default, the exporter evaluates a mature 24-hour exposure window ending 24 hours before
--end-timeand attributes clicks/bookings through--end-time; keep--label-attribution-window-hoursaligned with the training extractor before comparing CTR/CVR - the release gate requires the exporter snapshot metadata (
source=clickhouse,metric_family,collected_at, distinct non-empty baseline/candidate assignments, non-emptycandidate_strategy_ids,window.hours,window.end_time,window.label_event_end_time, andwindow.label_attribution_window_hours) and rejects CatBoost business snapshots that do not prove the default 24-hour mature exposure and 24-hour attribution windows or were collected before the label-event cutoff; override--catboost-ranker-min-business-window-hoursor--catboost-ranker-min-label-attribution-window-hoursonly for an experiment with an explicitly different attribution design - the exporter proves assignment and CatBoost serving from homepage impression request sets, attributes top-slot clicks back to the exposed
(request_id, item_id), and attributes bookings back byrequest_id; top-slot CTR counts one clicked/not-clicked outcome per exposed top-slot item request rather than raw duplicate click events; downstream click/booking events do not need to repeatstrategy_id, but bookings withoutrequest_idcannot support CVR evidence - candidate serving coverage is matched only to
candidate_catboost_rerank,selected_items_catboost_rerank, andsection_selected_items_catboost_rerank; repeat--candidate-strategy-idto override this set for a canary with a renamed strategy - use
scripts/monitoring/homepage_ranking_guardrails.sqlfor manual inspection or ad hoc ClickHouse validation of the same metric keys
Serving API V2 Gates
- Functional staging smoke checks pass for health, readiness, model info, cohort features, item features, homepage, refresh, homepage decision, and direct recommendations:
uv run python scripts/benchmark_serving_api_v2.py --base-url <staging-base-url> --member-user-id <known-featured-member-id> --iterations 20 --warmup-iterations 5 --fail-on-regression --output text
- Bounded in-cluster staging load passes before traffic promotion:
uv run python scripts/benchmark_serving_api_v2.py --base-url <staging-base-url> --member-user-id <known-featured-member-id> --iterations 20 --warmup-iterations 5 --load-requests 50 --load-concurrency 5 --fail-on-regression --output text
- Staging API latency evidence must be collected from in-cluster execution or a dedicated load-test runner. Local port-forward runs are acceptable only for functional reachability diagnostics.
- The checked-in serving API baseline is
recsys/serving/baselines/api_v2.json.
Data Quality Gates
- Feature availability ratio (member) >= 0.85.
- Ranker feature completeness ratio >= 0.99.
- No prolonged stale ANN index (
<= 24hp95 age). - No sustained fallback spikes beyond canary thresholds.
- Canary metric guardrail thresholds (must all pass):
- homepage p95 latency <= 1.0s
- homepage fallback ratio <= 0.10
- homepage decision p95 latency <= 0.25s
- homepage decision fallback ratio <= 0.02
- refresh timeout-terminalized ratio <= 0.02
- member feature availability ratio >= 0.85
- ranker decision failure ratio <= 0.05
- personalization queue depth max <= 100
- pending refresh age seconds max <= 45
- worker failure ratio <= 0.10
- ANN index age p95 <= 24h
- CatBoost ranker business guardrails pass before canary expansion:
- candidate top-slot CTR beats baseline by
>= 0.001absolute - candidate booking CVR beats baseline by
>= 0.001absolute - candidate and baseline sample counts meet the configured minimums
- candidate top-slot CTR beats baseline by
- Restaurant cutover validation passes:
uv run python scripts/validate_restaurant_cutover.py --sample-query buffet --sample-query omakase --sample-query "rooftop bar"
- If snapshot evidence is available, validate guardrails with:
uv run python scripts/export_canary_metrics_snapshot.py --prometheus-url http://<prometheus-host>:9090 --output artifacts/release/canary-metrics.jsonuv run python scripts/release_readiness.py --metrics-snapshot artifacts/release/canary-metrics.json
- For one-step execution with live Prometheus metrics, use:
uv run python scripts/release_readiness.py --prometheus-url http://<prometheus-host>:9090 --metrics-output artifacts/release/canary-metrics.json
Performance Gates
- Homepage p95 latency under release threshold (1.0s absolute max).
- Ranker fallback latency and regular ranking latency are within existing test budgets.
- Queue depth and pending refresh age are stable during canary windows.
- Feast v2 online lookup p95/p99, historical retrieval throughput, publication throughput, and payload-size regression gates pass through
--with-feature-store-v2-gates. - Serving API v2 functional, latency, and bounded-load gates pass through
scripts/benchmark_serving_api_v2.py. - Redis and ClickHouse capacity validation uses measured
FEATURE_STORE_V2_*cardinality and payload-size inputs before serving is enabled.
Required capacity variables for --feature-store-v2-capacity-from-env:
FEATURE_STORE_V2_ACTIVE_MEMBERSFEATURE_STORE_V2_ACTIVE_ITEMSFEATURE_STORE_V2_ACTIVE_COHORTSFEATURE_STORE_V2_MEMBER_PAYLOAD_BYTESFEATURE_STORE_V2_ITEM_PAYLOAD_BYTESFEATURE_STORE_V2_COHORT_PAYLOAD_BYTESFEATURE_STORE_V2_DAILY_MEMBER_ROWSFEATURE_STORE_V2_DAILY_ITEM_POPULARITY_ROWSFEATURE_STORE_V2_DAILY_ITEM_METADATA_ROWSFEATURE_STORE_V2_DAILY_COHORT_ROWSFEATURE_STORE_V2_RETENTION_DAYS(optional; defaults to 730)FEATURE_STORE_V2_REDIS_REPLICATION_FACTOR(optional; defaults to the capacity planner default)
Security/Operational Gates
- Required secrets present for target environment:
CACHE_HMAC_SECRET(production-safe mode)PROMETHEUS_BEARER_TOKEN(if release workflow exports canary snapshot)
- Required GitHub Actions variables for release workflow:
PROMETHEUS_URL(optional; enables automatic canary snapshot export + artifact upload)
- No mock/synthetic production paths enabled.
- Runbooks are linked in alerts and accessible to on-call.
Rollout Confirmation
- Canary progression completed:
5% -> 25% -> 50% -> 100%. - No critical auto-rollback alerts triggered during each stage.
- Post-rollout observation window (minimum 24h) is stable.
Evidence To Attach
- CI run URL and commit SHA.
- Canary dashboard snapshots.
- MLflow run ID/model version promoted.
- ANN rebuild run ID and timestamp.
Related Docs
docs/canary_rollout_runbook.mddocs/runbooks/canary_dashboard_spec.mddocs/runbooks/model_rollback_runbook.mddocs/runbooks/retrain_reindex_playbook.md