#118 — Redis durch datenbank-gestützte Sessions ersetzen (infra) #121
Labels
No labels
priority/could
priority/must
priority/should
priority/wont
status/blocked
status/claimed
status/done-migrated
type/bug
type/feature
type/infra
type/tech-debt
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
robert/todo#121
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Story: Redis durch datenbank-gestützte Sessions ersetzen (infra)
As a Betreiber der App,
I want to dass Sessions in der bestehenden PostgreSQL-Datenbank statt in einer separaten Redis-Instanz
gespeichert werden,
so that der Betrieb eine externe Komponente weniger braucht (Deployment, Backup, Monitoring, ein
zusätzlicher Service in
docker-compose.yml), ohne dass sich am Session-Verhalten für Nutzer etwas ändert.Confirmed by reading the code (2026-08-10): Redis wird aktuell ausschließlich als
IDistributedCache-Backendfür
AddSession()genutzt (CqsTodo.WebApi/Program.cs:148-150,AddStackExchangeRedisCache→AddSession).Keine andere Stelle im Code verwendet Redis (kein Output-Caching, kein Rate-Limiter-Backend — der Login-Rate-
Limiter läuft in-memory). Es gibt keinen früheren Umstieg auf DB-Sessions — das war ein Missverständnis; die
Architektur war und ist "PostgreSQL · Redis (sessions)" (siehe
ai/roles/00_team_overview.md, "Shared context").Einordnung: Infrastruktur-Story — läuft laut
ai/roles/00_team_overview.md, "Infrastructure cycle", durchden leichtgewichtigen Zyklus (PO-Scope → Architect-Design-Note → Security-Vorprüfung → Implementierung → QA),
nicht den vollen Feature-Zyklus mit Frontend-Anteil, da rein serverseitig.
Depends on: nichts blockierendes. Berührt aber
#59(Remember-me/persistent login) und dessenRevocation-Mechanismus (
SessionsRevokedBeforeUtc,SessionMaintenanceMiddleware,DestroyCurrentSessionCommand) — deren Verhalten muss unverändert erhalten bleiben, siehe AC unten.Acceptance criteria:
IDistributedCache-Implementierung auf Basis der bestehendenTodoDatabase-Postgres-Instanz gespeichert (z. B. via EF Core und einer neuenSessions/Cache-Tabelle,oder einer geeigneten Postgres-
IDistributedCache-Bibliothek — konkrete technische Wahl liegt beimArchitect, siehe Open Questions).
#59:SessionPolicy.MaxLifetime, 30 Tage) und rollierendes Cookie-Refresh(
SessionMaintenanceMiddleware, 24h-Intervall) funktionieren identisch.RevokeAllSessionsForCurrentUserCommand+GetSessionsRevokedBeforeUtcQuery)funktioniert identisch — dieser Mechanismus existiert gerade weil einzelne Redis-Records nicht adressierbar
sind (siehe
GetSessionsRevokedBeforeUtcQuery.cs-Kommentar); das DB-Backend darf hier keine Abkürzung nehmen,die diesen Kommentar falsch macht, ohne ihn zu aktualisieren.
DestroyCurrentSessionCommand(Logout, Account-Löschung) leert weiterhin den kompletten Session-Record.HttpOnly,SameSite=Strict,Secure(sieheai/roles/00_team_overview.md, "Security baseline").beim Deploy dieser Story ist akzeptabel (muss aber im PR/Release-Hinweis explizit stehen, nicht stillschweigend
passieren).
docker-compose.yml,docker-compose.dev.yml,Aspire/AppHost.cs,.env.dev.example,CqsTodo.WebApi.csproj(StackExchange.Redis-Paket),.gitea/workflows/ci.yml(falls dortein Redis-Service für Tests hochgefahren wird), sowie die "Redis (sessions)"-Erwähnung im Stack-Eintrag von
ai/roles/00_team_overview.md.SessionMaintenanceMiddleware) keine spürbare Zusatzlast auf der ohnehin von der App genutztenPostgres-Instanz erzeugen (z. B. durch Wahl/Indexierung des Schemas) — kein separates Lastproblem einführen,
um ein Betriebsproblem zu lösen.
Out of scope for this story:
gewünscht wird, ist das eine neue, separate Story.
(falls DB-Sessions hier andere Grenzen haben, ist das ein Architect-Hinweis, keine neue Anforderung dieser Story).
Open questions (an den Architect):
IDistributedCache-Implementierung über EF Core/Npgsql, oder eine bestehendePostgres-
IDistributedCache-Bibliothek? Abwägung: zusätzliche Abhängigkeit vs. selbst zu wartender Code.einen äquivalenten Mechanismus, z. B. Lazy-Delete beim Zugriff oder ein periodischer Cleanup-Job).