Central Redis
French version: ../redis.md.
Role (kit rule 6.2)
Redis is a cache and temporary coordination: rate limit counters, a per tenant cache that can be encrypted (eai.cache), distributed locks with a fencing token. It is never the only source of truth for permissions, suspensions, quotas or evidence: those are read from PostgreSQL. tests/test_core_redis.py::test_sources_of_truth_never_read_from_redis refuses any Redis or eai.cache import in those modules.
Connection, TLS and ACL
EAI_REDIS_URL=rediss://redis.internal:6390/0,EAI_REDIS_USERNAME=eai,EAI_REDIS_PASSWORD_FILE=/run/secrets/redis-password,EAI_REDIS_TLS_CA_FILE=/etc/eai/redis-ca.pem(server certificate verified). In prod the startup refusesredis://and a URL without a password (file).- Minimal ACL user:
ACL SETUSER eai on >... ~eai:* +@all -@dangerous(keys prefixedeai:). - Keys:
eai:c:<tenant>:<namespace>:<name>(cache, mandatory TTL from 1 s to 7 days),eai:rl:*(rate limits, one minute window). /readyzpublishesredis: {configured, ok, role, error}without making the instance not ready.
High availability
deploy/data/redis(OT redis-operator): replication with sentinels and TLS. After a failover the client reconnects to the new primary; verified with a realredis-server:--replicaofreplica, primary stopped (the cache answers miss without error),REPLICAOF NO ONEpromotion, read and write on the new primary.
Redis down
- Cache: read = miss, write =
False, lock refused. Rate limiting: falls back to the in-memory counters of each replica (warning logged). The API keeps serving.
Backup
- None: the content is rebuilt. Persistence may be disabled.
Tests
cd services/control-plane && .venv/bin/python -m pytest -q tests/test_core_redis.py (starts /usr/bin/redis-server on free ports): TTL, tenant isolation, encrypted entry bound to its key, lock and fencing, rate limit shared by two instances, replication and failover, ACL with password file, Redis stopped.