> For the complete documentation index, see [llms.txt](https://framework.aic.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://framework.aic.io/technical-guidelines-code-standards-and-tech-stack/solution-and-architecture-standards/caching-strategy.md).

# Caching Strategy

## AIC Standard

Redis is the default distributed caching technology for AIC systems.

Caching must be deliberate. It should improve performance, resilience or cost efficiency without weakening correctness, security or auditability.

Redis must not become an uncontrolled secondary database.

## When to Use Redis

Use Redis for:

* frequently accessed reference data
* expensive read queries that can tolerate staleness
* API response caching
* distributed rate limiting
* short-lived idempotency keys
* short-lived distributed coordination
* user session state where required
* temporary workflow hints that can be rebuilt
* background job coordination where loss is acceptable or backed by durable state

Do not use Redis for:

* authoritative business records
* permanent audit data
* long-running workflow state unless backed by durable persistence
* sensitive data without explicit security review
* secrets
* data that cannot be regenerated

## Cache Design Requirements

Every cache must define:

* purpose
* owner
* cached data type
* source of truth
* key format
* expiry policy
* invalidation trigger
* maximum acceptable staleness
* security classification
* failure behaviour
* monitoring approach

## Cache Key Standard

Cache keys must be predictable, namespaced and tenant-aware where applicable.

Recommended pattern:

```
{system}:{environment}:{tenantId}:{resource}:{identifier}:{version}
```

Example:

```
aic:prod:org-123:case-summary:case-456:v1
```

Rules:

* include tenant or organisation where data is tenant-owned
* include environment to prevent accidental cross-environment pollution
* include version where schema changes are possible
* avoid raw personal data in keys
* keep keys stable and documented

## Expiry Standard

Every Redis key must have an expiry unless there is a documented exception.

Expiry should reflect the business tolerance for stale data.

| Data type          |                         Typical expiry |
| ------------------ | -------------------------------------: |
| API response cache |                30 seconds to 5 minutes |
| Reference data     |                    5 minutes to 1 hour |
| Rate-limit counter |              window length plus buffer |
| Idempotency key    |              business operation window |
| Distributed lock   | seconds, not minutes, unless justified |
| User session       |     customer or security policy-driven |

## Invalidation Standard

Invalidation must be explicit for critical cached data.

Valid approaches:

* time-based expiry
* event-driven invalidation
* write-through update
* explicit delete on source update
* versioned key rollover

Avoid complex invalidation logic unless there is a strong reason.

## Failure Behaviour

A system must define what happens when Redis is unavailable.

Possible behaviours:

* bypass cache and query source of truth
* degrade gracefully
* return controlled error for rate-limit dependent functions
* temporarily disable non-critical caching
* fail closed for security-sensitive cache use

The behaviour must be tested for critical services.

## Security Controls

Redis usage must follow these controls:

* no secrets in Redis
* no uncontrolled personal data
* encryption in transit where supported and required
* network restriction to approved services
* authentication enabled
* least privilege access where platform supports it
* monitoring for memory pressure and eviction
* keyspace separation by environment
* clear retention through expiry

## .NET Implementation Standard

Use `IDistributedCache` for simple cache operations where possible.

Use a Redis-specific client only when advanced features are required.

Example interface:

```csharp
public interface ICacheService
{
    Task<TValue?> GetAsync<TValue>(
        string cacheKey,
        CancellationToken cancellationToken);

    Task SetAsync<TValue>(
        string cacheKey,
        TValue value,
        TimeSpan expiry,
        CancellationToken cancellationToken);

    Task RemoveAsync(
        string cacheKey,
        CancellationToken cancellationToken);
}
```

## Quality Gate

Before release:

* Redis purpose documented
* cache keys documented
* expiry defined for every key type
* invalidation approach documented
* source of truth identified
* security review completed for sensitive data
* failure behaviour tested
* monitoring and alerting configured
