Cache Contracts: Enforceable Freshness SLAs for FINRA and SOC 2
Every cache has an implicit freshness promise. When your application reads a cached value, it assumes that value is still valid. But assumptions are not contracts. There is no mechanism in Redis, Memcached, or any conventional cache to define what "fresh" means, to enforce it, or to prove after the fact that every read returned data within an agreed-upon staleness window. This is a convenience shortcut when you are caching CSS files. It is a regulatory violation when you are caching FINRA-regulated trade data or SOC 2-scoped financial computations.
A cache contract is an enforceable agreement between the cache producer (the system that writes cached values) and the cache consumer (the system that reads them). The contract defines four things: the maximum staleness permitted for a given computation type, the verification requirements that must be met before a cached value is served, the audit trail depth that must be retained for compliance evidence, and the invalidation guarantees that ensure stale data is never silently served. These four properties transform a cache from a best-effort optimization into a compliance-grade data store with provable freshness guarantees.
FINRA Rule 4511 requires broker-dealers to preserve books and records in an accessible manner. When trade data is cached, the cached copy is a record. If that cached record is stale -- if it reflects a quote that has since been updated, a position that has since changed, or a risk calculation that has since been superseded -- then serving it to a trader, risk manager, or compliance officer is a regulatory violation. The cache is not exempt from record-keeping requirements simply because it is labeled "temporary." FINRA does not recognize "temporary" as a category that excuses data accuracy obligations.
What a Cache Contract Contains
A cache contract is a structured definition that binds a computation type to specific freshness, verification, and auditability requirements. It is not a configuration hint. It is an enforceable specification that the cache runtime evaluates on every read operation. If the contract cannot be satisfied, the cache returns a miss rather than serving data that violates the contract terms. This is the fundamental difference between a TTL and a contract: a TTL is a suggestion that can be ignored or overridden, while a contract is a hard constraint that the cache runtime enforces without exception.
Max Staleness (TTL with Teeth)
The max_staleness_ms field defines the maximum age of a cached value in milliseconds. Unlike a Redis TTL, which simply deletes the key after expiration, a Cachee contract's max staleness is checked at read time against the value's creation timestamp. If the value is older than the contract permits, the cache returns a miss with a VerificationStatus::Stale indicator, logs the staleness violation, and triggers recomputation. The stale value is not deleted -- it transitions to the Superseded state, preserving the audit trail. A Redis TTL silently removes the key. A Cachee contract preserves the evidence that a value existed, when it became stale, and what replaced it.
Verification Requirements
The verification section of a contract specifies which cryptographic checks must pass before a cached value is served. At minimum, this includes signature verification against all three post-quantum signature algorithms (ML-DSA-65, FALCON-512, SLH-DSA-SHA2-128f). For FINRA-regulated data, the contract can additionally require that the computation fingerprint matches the expected computation type, that the hardware class matches the authorized execution environment, and that the software version falls within an approved range. If any verification check fails, the cache returns a miss with a detailed VerificationStatus that identifies exactly which check failed and why.
Audit Trail Depth
The audit_trail_depth field specifies how many historical versions of a cached value must be retained for compliance purposes. FINRA Rule 4511 requires six years of record retention for most books and records, with three years in an easily accessible location. Setting audit_trail_depth to cover the retention window ensures that every version of a cached computation -- including superseded and revoked versions -- is preserved with its full signature chain, fingerprint, and state transition history. This means an examiner can reconstruct the exact cached value that was served to a trader at any point during the retention period, verify its signatures, and confirm that it was within its freshness contract at the time it was served.
Invalidation Guarantees
The invalidation section defines what happens when source data changes. In a traditional cache, invalidation is fire-and-forget: you send a delete command, and if it arrives, the key is removed. If the network drops the invalidation message, the stale value persists until TTL expiration. Cachee contracts support three invalidation modes. Eager invalidation pushes invalidation events to all cache nodes immediately when source data changes. Versioned invalidation increments a version counter in the computation fingerprint, causing all cached values with the old version to fail fingerprint verification on next read. Contractual invalidation defines invalidation as a contract term: if the source system has not confirmed freshness within the contract window, the cached value is treated as unverified regardless of its age.
FINRA Compliance Alert: Stale Cache Is a Regulatory Violation
FINRA Rule 3110 requires broker-dealers to establish supervisory systems that are reasonably designed to achieve compliance. If your trading system caches quote data and serves stale quotes because your cache has no freshness enforcement, your supervisory system is deficient. A cache contract with defined max staleness, verification requirements, and invalidation guarantees is evidence that your supervisory system covers cached data. Absence of a contract is evidence that it does not.
The Cache Contract Lifecycle State Machine
Every cached value governed by a contract moves through a defined state machine. There are four states, and every transition between states is logged with a TransitionAuthority (which key authorized the transition) and a TransitionProof (a cryptographic proof that the transition was valid). The state machine is not optional. It is enforced by the cache runtime on every operation.
Active. The value was written within its contract's freshness window, all signatures are valid, and the computation fingerprint matches the expected parameters. The cache serves the value and returns a CacheeReadResponse with VerificationStatus::Valid, a freshness proof containing the value's age relative to its contract, and a SignatureSummary listing which algorithms verified successfully. This is the only state in which a value is served to consumers.
Superseded. A newer version of the value has been written. The old value transitions from Active to Superseded. The supersession is logged with the fingerprint of the new value, establishing a provenance chain. Superseded values are never served to consumers but are retained for audit trail depth requirements. A FINRA examiner can query superseded values to see the complete history of a cached computation over time.
Expired. The value's age has exceeded the max_staleness_ms defined in its contract. Expiration is detected at read time: if a consumer requests a value whose age exceeds its contract, the cache transitions the value to Expired, logs the transition, and returns a miss. The expired value is retained for audit purposes. This is fundamentally different from Redis TTL expiration, which deletes the key and destroys all evidence that the value ever existed.
Revoked. A value has been forcibly invalidated before its natural expiration. Revocation can be triggered by source data changes (invalidation guarantee), by a security event (compromised signing key), or by an administrative action (regulatory hold). Revoked values are never served and cannot transition back to Active. They are permanently marked as invalid, with the revocation reason, authority, and proof preserved in the transition log.
// Cache contract lifecycle state machine
//
// [Write] ──► Active ──► Superseded (new version written)
// │ │
// │ └──► [Retained for audit trail depth]
// │
// ├──► Expired (max_staleness_ms exceeded)
// │ │
// │ └──► [Retained for audit trail depth]
// │
// └──► Revoked (forced invalidation)
// │
// └──► [Retained for audit trail depth]
//
// Every transition produces:
// - TransitionAuthority (which key authorized)
// - TransitionProof (cryptographic proof of validity)
// - Timestamp (nanosecond precision)
Contract Definition and Enforcement
A cache contract is defined per computation type. Different types of cached data have different freshness requirements, different verification needs, and different audit retention periods. A FINRA-regulated quote cache has a 500-millisecond staleness window and six-year retention. A SOC 2-scoped session cache has a 30-minute staleness window and 400-day retention. A general-purpose API response cache might have a 60-second staleness window and 90-day retention. Each contract is independent and enforced independently.
# cachee.toml — Contract definitions for financial services
[contracts.finra_quotes]
computation_type = "market_quote"
max_staleness_ms = 500
verification = ["ML-DSA-65", "FALCON-512", "SLH-DSA-SHA2-128f"]
fingerprint_fields = ["symbol", "exchange", "quote_type", "feed_version"]
audit_trail_depth_days = 2190 # 6 years per FINRA Rule 4511
invalidation = "eager"
strict_mode = true # never serve stale, always return miss
[contracts.soc2_sessions]
computation_type = "user_session"
max_staleness_ms = 1800000 # 30 minutes
verification = ["ML-DSA-65", "FALCON-512", "SLH-DSA-SHA2-128f"]
fingerprint_fields = ["session_id", "user_id", "auth_method", "client_ip"]
audit_trail_depth_days = 400 # SOC 2 Type II requires 365+
invalidation = "versioned"
strict_mode = true
[contracts.risk_calculations]
computation_type = "portfolio_risk"
max_staleness_ms = 5000 # 5 seconds
verification = ["ML-DSA-65", "FALCON-512", "SLH-DSA-SHA2-128f"]
fingerprint_fields = ["portfolio_id", "risk_model_version", "market_data_timestamp"]
audit_trail_depth_days = 2190 # 6 years
invalidation = "contractual"
strict_mode = true
At runtime, every cache read evaluates the contract for the requested computation type. The following pseudocode shows the enforcement logic that executes on every GET operation.
// Contract enforcement on every cache read
fn cache_read(key: &CacheKey, contract: &CacheContract) -> CacheeReadResponse {
let entry = self.store.get(key);
match entry {
None => CacheeReadResponse::miss(key, "no_entry"),
Some(entry) => {
// 1. Check freshness against contract
let age_ms = now() - entry.created_at;
if age_ms > contract.max_staleness_ms {
entry.transition_to(State::Expired, TransitionAuthority::Contract);
self.audit_log.record_staleness_violation(key, age_ms, contract);
return CacheeReadResponse::miss(key, "contract_expired");
}
// 2. Verify all required signatures
let sig_results = contract.verification.iter()
.map(|alg| entry.verify_signature(alg))
.collect::<Vec<_>>();
if sig_results.iter().any(|r| !r.is_valid()) {
entry.transition_to(State::Revoked, TransitionAuthority::Verification);
self.audit_log.record_signature_failure(key, &sig_results);
return CacheeReadResponse::miss(key, "signature_verification_failed");
}
// 3. Verify computation fingerprint
let expected_fp = compute_fingerprint(&contract.fingerprint_fields);
if entry.fingerprint != expected_fp {
entry.transition_to(State::Revoked, TransitionAuthority::Fingerprint);
self.audit_log.record_fingerprint_mismatch(key, &entry.fingerprint, &expected_fp);
return CacheeReadResponse::miss(key, "fingerprint_mismatch");
}
// 4. All checks pass — serve the value
CacheeReadResponse {
value: entry.value.clone(),
verification_status: VerificationStatus::Valid,
freshness_proof: FreshnessProof {
age_ms,
max_staleness_ms: contract.max_staleness_ms,
headroom_ms: contract.max_staleness_ms - age_ms,
},
signature_summary: SignatureSummary::from(&sig_results),
fingerprint: entry.fingerprint.clone(),
}
}
}
}
Every read response includes the freshness_proof field, which tells the consumer exactly how old the value is relative to its contract. This is not metadata that the consumer has to opt into. It is part of every response. A compliance system can aggregate freshness proofs across all cache reads to demonstrate that no read during the audit period served a value outside its contract window. This is the evidence that auditors require and that no conventional cache can produce.
Contract Violation Handling
When a contract is violated, three things happen simultaneously. First, the cache returns a miss to the consumer, ensuring that the stale or invalid value is never served. Second, the violation is recorded in the audit log with the full context: which contract was violated, which check failed, the exact age or signature status of the value, and the key that requested the read. Third, an alert is generated for the operations team or compliance team, depending on the contract type. FINRA contract violations generate compliance alerts. SOC 2 contract violations generate security alerts (see our guide on SOC 2 cache infrastructure controls for the full list of seven required controls). General contract violations generate operational alerts.
Contract violations also trigger automatic recomputation. When a cache returns a miss due to contract violation, the cache client library initiates a fresh computation of the requested value. The fresh result is written to the cache with new signatures and a new fingerprint, transitioning the old value to Superseded. This closed loop ensures that contract violations are self-healing: a stale value is detected, rejected, replaced, and logged in a single read cycle. There is no window in which a consumer can receive stale data because the enforcement happens before the value is returned, not after.
Redis TTL vs Cachee Contracts: A Direct Comparison
Redis TTL and Cachee contracts both address data freshness, but they operate at fundamentally different levels of rigor. Understanding the differences is essential for any team that needs auditable freshness guarantees rather than best-effort expiration.
| Capability | Redis TTL | Cachee Contract |
|---|---|---|
| Freshness definition | Single integer (seconds or ms) | Structured contract per computation type |
| Enforcement point | Background expiration thread | Every read operation (synchronous) |
| Stale value behavior | Key deleted silently | State transition to Expired, audit log entry, alert |
| Evidence of freshness | None (key exists or does not) | FreshnessProof with age, max staleness, headroom |
| Audit trail | None | Full transition history with authority and proof |
| Signature verification | Not supported | Three PQ signatures verified on every read |
| Fingerprint binding | Not supported | SHA3-256 fingerprint checked against contract fields |
| Violation alerting | Not supported | Automatic alerts by contract type |
| Recomputation trigger | Cache miss (no context) | Contract violation with full context for recomputation |
| Regulatory evidence | Cannot be produced | Native export of freshness proofs, violations, transitions |
The core difference is that Redis TTL operates at the infrastructure level -- it manages key lifetimes. Cachee contracts operate at the compliance level -- they manage data freshness obligations. A Redis TTL answers the question "is this key still alive?" A Cachee contract answers the question "is this data still compliant?" These are fundamentally different questions, and only one of them matters to a FINRA examiner or SOC 2 auditor.
FINRA-Specific Contract Requirements
FINRA-regulated firms face specific requirements that go beyond general SOC 2 controls. Trade data, quote data, order data, and risk calculations all have freshness requirements defined by regulation, not by engineering convenience. A cache that serves a stale best-bid-offer is not just slow -- it is a potential best execution violation under FINRA Rule 5310. A cache that serves a stale position to a risk manager is not just inaccurate -- it is a potential net capital violation under SEC Rule 15c3-1.
Cache contracts for FINRA-regulated data must include several additional properties beyond the base contract specification. The regulatory_classification field identifies the data type for FINRA purposes (quote, order, trade, position, risk). The books_and_records_category field maps the cached data to its FINRA Rule 4511 retention category. The supervisory_review_required flag indicates whether contract violations must be reviewed by a registered principal under FINRA Rule 3110. And the examination_export_format field specifies the format in which cached data must be exportable for FINRA examination requests.
# cachee.toml — FINRA-specific contract extensions
[contracts.nbbo_quotes]
computation_type = "nbbo_quote"
max_staleness_ms = 250 # sub-second for best execution
verification = ["ML-DSA-65", "FALCON-512", "SLH-DSA-SHA2-128f"]
fingerprint_fields = ["symbol", "exchange", "sip_timestamp", "feed_handler_version"]
audit_trail_depth_days = 2190
invalidation = "eager"
strict_mode = true
# FINRA-specific extensions
regulatory_classification = "quote"
books_and_records_category = "4511(c)"
supervisory_review_required = true
examination_export_format = "FINRA-XML"
[contracts.order_state]
computation_type = "order_cache"
max_staleness_ms = 100
verification = ["ML-DSA-65", "FALCON-512", "SLH-DSA-SHA2-128f"]
fingerprint_fields = ["order_id", "oms_version", "routing_table_version"]
audit_trail_depth_days = 2190
invalidation = "eager"
strict_mode = true
regulatory_classification = "order"
books_and_records_category = "4511(b)"
supervisory_review_required = true
examination_export_format = "FINRA-XML"
SOC 2 Processing Integrity and Cache Freshness
SOC 2 Trust Service Criterion CC7.1 (Processing Integrity) requires that system processing is complete, valid, accurate, timely, and authorized. The word "timely" is the one that applies to cache freshness. If your system caches a computation result and serves it to a user or downstream system, the result must be timely -- meaning it must reflect the current state of the underlying data within a defined and auditable window.
Without cache contracts, you have no definition of "timely" for cached data. You have a Redis TTL that expires keys on a best-effort basis, but you have no evidence that every read during the audit period received data within an acceptable staleness window. You cannot produce a report showing "zero freshness violations in the last 365 days" because you have no mechanism to detect freshness violations, let alone log them.
Cachee contracts make SOC 2 Processing Integrity evidence trivial to produce. Every cache read returns a FreshnessProof. Every contract violation is logged. At audit time, you export the violation log, which shows zero violations (proving that all reads were timely) or shows specific violations with their resolution (proving that violations were detected, alerted, and resolved per policy). Either way, you have evidence. Without contracts, you have nothing.
SOC 2 Evidence: Cache Freshness Is Now Auditable
Every CacheeReadResponse includes a FreshnessProof with the value's age, the contract's max staleness, and the remaining headroom. Every contract violation produces an audit log entry with full context. At audit time, export the freshness proof aggregates and violation log. This is the evidence that SOC 2 Processing Integrity requires -- and that no conventional cache can produce.
Implementing Cache Contracts: Step by Step
Implementing cache contracts in a production system requires four steps. Each step builds on the previous one, and each produces compliance evidence independently. You do not need to complete all four steps before any evidence is available. Step one alone gives you auditable freshness. Step four gives you full regulatory readiness.
Step 1: Define contracts per computation type. Inventory every type of data your system caches. For each type, determine the maximum acceptable staleness, the verification requirements, the audit retention period, and the invalidation strategy. Write these as Cachee contract definitions in your cachee.toml. This step typically takes one to two days and produces the contract specification document that auditors will reference.
Step 2: Enable enforcement. Set strict_mode = true on all contracts. This causes the cache to return misses rather than serve values that violate their contracts. Monitor the miss rate for the first week to identify any contracts with overly aggressive staleness windows. Adjust the windows based on actual data freshness patterns, not guesses. The goal is the tightest staleness window that does not cause unnecessary recomputation.
Step 3: Configure alerting. Connect contract violations to your alerting infrastructure. FINRA contract violations should page the compliance team. SOC 2 contract violations should alert the security team. General contract violations should notify the engineering team. Each alert includes the full violation context: which contract, which check failed, the exact values that caused the failure, and the remediation action taken by the cache (miss returned, recomputation triggered).
Step 4: Configure evidence export. Set up scheduled exports of freshness proof aggregates, violation logs, and state transition histories. These exports feed into your SOC 2 evidence repository and your FINRA books and records archive. Configure the export format, schedule, and retention to match your compliance requirements. Test the export by producing a sample report and reviewing it with your auditor.
The Cost of Not Having Contracts
The cost of operating a cache without contracts is not measured in latency or throughput. It is measured in regulatory risk and audit findings. A FINRA examination that discovers cached trade data without freshness enforcement will result in a deficiency finding. A SOC 2 Type II audit that cannot produce evidence of timely data processing for cached computations will result in an exception in the Processing Integrity criterion. Both findings are visible to customers, counterparties, and regulators. Both require remediation. Both could have been prevented by defining and enforcing cache contracts from the start.
The engineering cost of cache contracts is minimal. Contract definitions are configuration, not code. Enforcement is built into the Cachee runtime. Evidence export is a scheduled job. The total implementation effort for a team that is already using Cachee is one to two weeks, most of which is spent inventorying cached data types and determining appropriate staleness windows. The cost of not implementing contracts -- a FINRA deficiency finding or a SOC 2 exception -- is weeks of remediation, management attention, and customer trust erosion.
The Bottom Line
Cache contracts transform your cache from a best-effort optimization into a compliance-grade data store with enforceable freshness guarantees. Every read returns a freshness proof. Every violation is logged and alerted. Every state transition is cryptographically provable. FINRA examiners can verify that cached trade data was fresh at the time it was served. SOC 2 auditors can verify that all cached computations met their timeliness obligations. Redis TTL gives you key expiration. Cachee contracts give you regulatory compliance. The difference is the difference between hoping your cache is fresh and proving it.
Stop hoping your cache is fresh. Start proving it. Cachee contracts enforce freshness SLAs for FINRA and SOC 2 with zero code changes.
Get Started Cache Attestation Docs