Refactor upstream token storage from STRING+SET to HASH with per-field TTL
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 2.2k
- Forks
- 300
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 184
Description
Summary
The current upstream token storage in Redis uses one STRING key per provider per session plus a SET index to track all providers for a session. This can be simplified to a single HASH per session, where each field is a provider name and the value is the JSON token blob. Redis 7.4+ / Valkey 9.0+ support per-field HEXPIRE, allowing independent TTLs on each provider's tokens within the hash.
This refactor would:
- Eliminate the session index SET (
upstream:idx:{sid}) entirely - Reduce
GetAllUpstreamTokensfrom 2 round trips to 1 (HGETALLinstead ofSMEMBERS+MGET) - Simplify
DeleteUpstreamTokensfrom N+1DELcommands to a singleDEL - Remove key-string parsing to extract provider names
- Net reduction of ~50 lines of code with no interface changes
Prerequisites
- Redis >= 7.4 for per-field
HEXPIREsupport - Valkey >= 9.0 for per-field
HEXPIREsupport (valkey.io/commands/hexpire) - go-redis v9.18.0 (already in use) supports
HExpire - miniredis v2.37.0 (already in use) supports
HEXPIRE(seconds precision only)
Current Blocker
AWS ElastiCache supports up to Valkey 8.2 as of March 2026. There is no public timeline for Valkey 9.0 support. Since ToolHive deployments may run on ElastiCache, this refactor cannot ship until ElastiCache offers Valkey 9.0+.
Design
The full design is documented in docs/arch/12-upstream-hash-refactor.md. Key design decisions from expert review:
- Use
HEXPIRE(seconds) everywhere, notHPEXPIRE-- second precision is sufficient and has broader support HSETclears any existing field TTL, soHEXPIREmust always followHSET- Skip
HEXPIREwhenPTTLreturns-1(no-expiry tokens) - Migration idempotency: use
HEXISTS(hashKey, provider)notEXISTS(newKey) - Orphaned index SETs expire via existing TTLs -- no explicit cleanup needed
- One-way migration; old binaries gracefully degrade (users re-auth)
Estimated Impact
- ~150 lines removed, ~100 lines added (~50 net reduction)
- 5 files modified, no interface changes, no caller changes
- One-shot startup migration from STRING+SET to HASH layout
Generated with Claude Code
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read docs/arch/12-upstream-hash-refactor.md first, then locate the upstream token Redis storage and startup migration entry points described by the design. Confirm the Redis and Valkey version prerequisites, including the ElastiCache blocker, before undertaking the five-file refactor; done means the documented HASH layout, per-field TTL behavior, and one-shot migration are implemented without interface changes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, redis
- Domain
- backend, databases
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100