perf(hydra): remove expired tokens on a bounded schedule #69
Loading…
Reference in a new issue
No description provided.
Delete branch "perf/hydra-token-janitor"
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?
Problem
Hydra issues one access token per agent poll and nothing removed the expired rows. Measured on the cluster on 2026-09-06:
hydra_oauth2_accessrowshydra_oauth2_accesssizehydradatabase sizeNo
hydra janitorran anywhere: there were no CronJobs in theorynamespace.The companion change in
sean/binjovimakes the agents reuse one token per hour instead of one per poll, which stops most of the growth. This change removes the rows that already exist and the ones the remaining traffic still creates.Change
An hourly
CronJob/hydra-janitorinmanifests/stack:hydra janitor --tokenson the pinned server imageoryd/hydra:v2.3.0, so its idea of an expired token is the running server's idea.hydra-configConfigMap with--config /etc/hydra/hydra.yaml, so it applies the configuredttlblock rather than a second copy of those numbers that could drift.hydra-secretsSecret with--read-from-env. No connection string appears in the manifest.--keep-if-younger 1h,--batch-size 500,--limit 50000. The existing backlog clears over about seven runs; the steady state is far below one run's limit.concurrencyPolicy: Forbid,startingDeadlineSeconds: 300,restartPolicy: Never, and the same pod hardening as the rest of the stack.Scope is deliberately
--tokensonly.hydra_oauth2_codeholds 13 rows and the login and consent request tables are under a megabyte, so--requestsand--grantswould delete from tables that have no growth problem.What this does not do
DELETEleaves the pages in the table for PostgreSQL to reuse. The 513 MB file stays 513 MB and stops growing. Returning that space to the filesystem needsVACUUM FULLorpg_repack, which takes an exclusive lock on the table Hydra writes to on every token grant. That stays an operator decision.Tests
tests/hydra-janitor-contract.sh, wired intotests/check.sh. It pins the scope, the bounds, the shared image and config, the credential source, and the pod hardening.The guard is proved non-vacuous: from a green baseline, twelve damage cases are each rejected, including the image drifting from the server image, the scope widening to
--requests, the row-age floor or per-run limit being removed, concurrent runs being permitted, a DSN being spelled out, and the pod being allowed to run as root or write its root filesystem.kubectl apply --dry-run=serveraccepts the manifest.https://claude.ai/code/session_015dkyh6itUFos3aSZnomh2w