Skip to content

feat(sessions): drop DynamoDB, move sessions onto the Valkey cluster#80

Merged
stevethomas merged 2 commits into
mainfrom
claude/wizardly-volhard-f1911a
Jun 3, 2026
Merged

feat(sessions): drop DynamoDB, move sessions onto the Valkey cluster#80
stevethomas merged 2 commits into
mainfrom
claude/wizardly-volhard-f1911a

Conversation

@stevethomas
Copy link
Copy Markdown
Member

Hey, I made a thing! 🥳

Great! Now please answer the following questions to help out your assigned reviewer:

What problems are you solving?

Abandoning DynamoDB entirely. Sessions belong on Valkey — strong read-after-write consistency (~1 ms), and cache already runs there via cache.store: redis. This rips DynamoDB out of YOLO end-to-end and lands sessions on the existing shared Valkey cluster, isolated from cache by Redis logical database.

  • DynamoDB removed end-to-end — deleted the DynamoDb client wrapper, the SessionsTable resource, its sync:app step, the DynamoDb enum, the task-role dynamodb:* IAM grant, the DYNAMODB_CACHE_TABLE injection, and the build-time aws/aws-sdk-php gate. Zero dynamo hits left in src/ bar the deliberate validator reject.
  • Default flip — any app with tasks.web now defaults session.driver to redis (was dynamodb).
  • Redis session injectionsession.driver: redis injects SESSION_DRIVER=redis only, not SESSION_CONNECTION. A null connection routes Laravel's redis session handler to the stock default connection (DB 0) while cache stays on the cache connection (DB 1) — same Valkey instance, separate keyspace. Relies on cluster-mode-disabled Valkey (the YOLO default).
  • Validator — hard-fails session.driver: dynamodb with "session.driver: dynamodb is no longer supported — use redis"; allowed set is now redis | database | cookie | file. The redis-needs-cache guard checks the effective driver, so a web app that opts the cache out (cache.store: file) without re-pinning sessions is also caught. database | cookie | file stay pin-only.
  • Docs — DynamoDB stripped from manifest.md, provisioning.md, commands.md, scaling.md; documents that redis sessions live on the default connection (DB 0), separate from cache (DB 1), and that this relies on cluster-mode-disabled Valkey.

Validation: 514 Pest passed (1237 assertions) · pint clean · phpstan 0 errors · VitePress build green (fails on dead links, so cross-links are valid).

Is there anything the reviewer needs to know to deploy this?

Out of scope for this PR (not implemented — follow-ups):

  • One-time logout on cutover. The dynamo→redis switch is a different session store, so the first deploy invalidates every existing session — all users are logged out once.
  • Orphaned tables. Already-provisioned …-sessions DynamoDB tables are no longer managed by YOLO and need manual per-app teardown (CL first).
  • No session HA on a single node. Sessions now share the single Valkey node, so a node loss logs users out — recommend a Multi-AZ replica (IncreaseReplicaCount + automatic failover) as a follow-up.

Deploy consequence: an app with tasks.web and no cache:/session: block (e.g. CL) defaults both to redis and validates clean. An app that had opted the cache out to file without also pinning a non-redis session.driver will now hard-fail validation by design — re-pin the session driver before deploying.

🤖 Generated with Claude Code

stevethomas and others added 2 commits June 3, 2026 14:26
Rip DynamoDB out of YOLO end-to-end and put sessions on the existing
shared Valkey cluster, isolated from cache by Redis logical database.

- Delete the DynamoDb client wrapper, the SessionsTable resource, its
  sync:app step, the DynamoDb enum, the task-role dynamodb:* grant, the
  DYNAMODB_CACHE_TABLE injection, and the build-time aws-sdk-php gate.
- Flip the web-app default session.driver from dynamodb to redis.
- redis sessions inject SESSION_DRIVER only (no SESSION_CONNECTION) so
  the null connection routes to the stock default connection (DB 0),
  separate from the cache connection (DB 1) — same Valkey instance,
  separate keyspace. Relies on cluster-mode-disabled Valkey.
- Validator hard-fails session.driver: dynamodb ("no longer supported —
  use redis") and hard-fails redis when cache provisioning is off,
  checked against the effective driver so a web app that opts the cache
  out without re-pinning sessions is caught too.
- database|cookie|file stay pin-only. Docs updated across manifest,
  provisioning, commands, scaling.

514 Pest / pint / phpstan / VitePress all green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a dedicated "Sessions and cache share the node, not the keyspace"
subsection to the provisioning guide: the two stock redis connections
(default=DB 0, cache=DB 1), how SessionManager::createRedisDriver()
routes sessions to the default connection via a null SESSION_CONNECTION,
and a warning that the split is inherited from the app's stock
config/database.php — not enforced by YOLO — so a collapsed/customised
redis config lets cache:clear flush sessions. Manifest reference cell
trimmed to point at the new section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@stevethomas stevethomas merged commit d372c39 into main Jun 3, 2026
5 checks passed
@stevethomas stevethomas deleted the claude/wizardly-volhard-f1911a branch June 3, 2026 05:33
stevethomas added a commit that referenced this pull request Jun 3, 2026
…sh DynamoDB removal (#83)

* feat(audit): flag orphaned resources of unmanaged services; finish DynamoDB removal

`yolo audit` now classifies a fourth status, `orphan`: a resource carrying a
YOLO ownership marker but of an AWS service YOLO no longer provisions (it has
no `Resources/` class, so a sync would never recreate it). Driven by
`Audit::SERVICE_BY_RESOURCE_GROUP`, whose keys mirror the `src/Resources/*`
directories — enforced by ManagedServicesTest — so dropping a service dir
auto-surfaces its leftovers and a still-managed service is never false-flagged.

This makes the DynamoDB sessions table left behind by #80 visible: it's still
tagged `yolo:app=<live app>` (so the ownership test alone read it as `ok`), but
YOLO has no DynamoDB resource any more, so it now shows as `orphan` — a clear
teardown candidate. Orphan takes precedence over ok/drift and is surfaced via a
warning + a red label, ordered cleanup-first within its scope.

Also finishes scrubbing DynamoDB from the codebase:
- drop the `session.driver: dynamodb` special-case in the manifest validator
  (the generic allow-list already rejects it) and its dedicated test
- remove the DynamoDB tombstone assertions/comments from the IAM and env-step
  tests
- fix the `yolo.yml` stub that still advertised `dynamodb` as the default
  session driver, and the manifest-reference deprecation note

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* refactor(audit): collapse to ok/unexpected + a Reason column

Following review: the four-way ok/drift/orphan/rogue taxonomy overloaded
"drift" — which already means attribute-level config mismatch in `yolo sync` —
and made the labels hard to keep straight. Audit is an ownership/inventory
check (tags + ARN service + cluster liveness), never a config check, so it
really has just two outcomes:

- `ok`         — accounted for
- `unexpected` — not accounted for, with a `reason`:
    - `no ownership tag`              (was rogue)
    - `service no longer provisioned` (was orphan — the DynamoDB table)
    - `app cluster gone`              (was drift)

The cause moves from a one-word status into a Reason column — a sentence beats
a label, and "drift" now means exactly one thing across YOLO. The `--drift`
flag becomes `--unexpected`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant