Skip to content

Discover session lifetime and deployment rollback validation

Status: passed, including independent cleanup verification. This establishes the tested session lifecycle and feature-switch behavior; it is not a production capacity or ranking-quality result.

The candidate at f35163950971baba92bc23416e84d213f0fed7bb combines the prior controlled-rollout changes with production commit 3b774ecb2c1f55ffc5bb68cf22865b2b0e13be84, without merge conflicts. The application code is the pinned Git content, deployed with its real Dockerfile and entrypoint. A test-only preload restricts network access and supplies authenticated, read-only metrics from the owned test resources.

Frozen protocol

Two isolated Railway apps share an owned PostgreSQL database and Redis. Each app has two CPUs, 2 GB memory, an eight-connection database pool, and admission limits of four concurrent requests, including at most two fresh requests. The database role permits 24 connections. Redis has a 1 GB container, 128 MiB noeviction memory, authentication, and private networking. There are 713 eligible synthetic story families plus six excluded/sibling fixtures.

App A uses a 100% cursor cohort. App B uses 0% with two synthetic account IDs in its allowlist; existing guest cursors must still continue there. Measurement, personalization and analytics capture are off. Neither app has usable provider credentials or external network access. Production app settings and data are outside this test.

Seven ordered phases must pass:

  1. Verify both application identities, health, metrics and empty session state.
  2. Leave one visit abandoned and traverse another through all 713 families, retaining the completed visit for retry.
  3. Reach the per-actor limit, recover a compatible live visit, reject a changed page-size request, and verify equal cross-instance retry.
  4. Reach the global 16-session limit, reject another actor without reserving a slot, and recover an existing actor's compatible visit.
  5. Observe the original, unmodified 3,600-second lifetime. Continue and retry an active visit midway through the hour; its original deadline must not change. Abandoned, completed and active visits must lose their payload, metadata and actor/global indexes naturally after their deadlines.
  6. Reject expired cursors without reallocating, then admit new visits for actors previously constrained by the actor and global limits.
  7. Change the master switch on A and deploy a new instance of the same source. Old cursors must receive an explicit restart response; fresh requests must receive the public legacy feed without a guest cookie. B must still replay and continue its existing visit without extending its original deadline.

The observer enumerates the union of payload and metadata keys, including orphans. It deduplicates Redis SCAN results before applying bounds. Global accounting uses actual sorted-set cardinality and key TTL, so expired scores alone cannot masquerade as successful index cleanup. Missing metadata fields remain null. Memory measurements include Redis allocation overhead; they are not serialized-payload lengths.

The parent allows 260 application requests, 150 metric requests and 75 minutes of traffic. Sampling targets 30 seconds, with a maximum permitted gap of 45 seconds across the full hour. Each runtime has a 90-minute watchdog. Setup has a 20-minute stage-admission deadline, followed by separately bounded cleanup; this is not a hard whole-run duration limit.

One runner owns the mutation lock and journals attempts before external effects. It does not retry uncertain uploads or redeploys. Cleanup verifies absence again in the current attempt before removing dependencies; saved removal flags cannot authorize Redis/database deletion after a failed reconciliation. Both passing traffic and confirmed cleanup are required for a successful run.

Verification and evidence identity

The merged source passed hosted build and typecheck, 399 focused server tests (two Windows Redis skips), and 131 client tests. Linux CI 35535340554 passed both jobs, including real Redis, warehouse regressions, temporal evaluation and the generated open-source boundary. The separate full local open-source verification encountered a concurrent tsup output-cleaning collision during tests. The test phase then passed with Turbo task concurrency set to one: seven tasks, zero cache hits, 3,527 tests passed and five skipped. Its earlier typecheck and build phases had passed. This validates the exported source but does not claim that the pre-existing parallel-build race is fixed.

The deployment harness passed 25 local checks. Independent review also exercised six focused cases for stale cleanup journals, uncertain deletion, current absence, duplicate scan results and key/page overflow. Seven offline traffic simulations passed; those simulations do not establish real TTL behavior.

  • Run: bfe83d43fe991680d0c7e6f55dd323bb.
  • Frozen plan SHA-256: 58382c44f0bdb327c03b90e0dcae197507f8dab37621977457238a6ad5004fee.
  • Context v3: 2,469 files, 71,794,165 bytes; manifest SHA-256 161b7348769b700aacb76c536abeac61ca827057e4ca9d2f71c0dca8035251a8.
  • Context payload SHA-256: 20d0eebffe3a07b136dbecfd40bf37e0ced5b5d3b164f6632be77e245f8f0697.
  • Ignored evidence files: lifecycle-deployment-plan-v1.json, lifecycle-deployment-resource-v1.json, lifecycle-deployment-result-v1.json, lifecycle-deployment-run-result-v1.json, and the independent final audit.

Observed results

All seven phases passed. Traversal returned all 713 eligible families across 15 pages with no missing or repeated family. Sixteen original visits completed a real, unmodified hour; continuing and retrying at the halfway point preserved their original deadlines. Payloads, metadata, and actor/global indexes expired naturally. Expired cursors returned restart responses and freed slots admitted new visits.

The master-switch redeployment returned explicit restart responses for old cursors, served the public legacy feed without a guest cookie for fresh requests, and preserved cross-server continuation on the zero-percent instance. There were 53 application requests and 133 metrics requests. Traffic took 60.8 minutes; setup, traffic and cleanup together took 66.2 minutes.

Cleanup removed all three temporary services, the owned database and its role without forced database disconnects. An independent audit at 2026-09-20T21:48:53Z confirmed absence and verified that the public application's flags remain off and its dedicated Discover Redis remains unwired. The separate production worker trial is outside this lifecycle test's zero-production-write scope.

  • Traffic result SHA-256: a16f0048ef54b45addfdc01b2682308c2668eca409cd2108f2f8689afcd5ca73.
  • Combined run receipt SHA-256: e20ff707466bceb063e02587975c3dffee275b9c741654fc1fd828d107851caa.
  • Independent audit SHA-256: 6db7d6b3b575932445d22af4b0f6664a8cee434f7ebd49f58467f95279f44f8c.

Limits

This tests guest session lifetime, shared-store accounting and a master-switch redeployment at a small synthetic envelope. It does not establish authenticated session lifetime, production Neon interference/capacity, Redis failover, an old binary/codec rollback, browser rendering, scheduled analytics ingestion, ranking quality or reader uplift. The experimental content ranking remains disabled after its earlier failed offline comparison.