Cache Strategy
Configure cache storage, permissions, lifecycle, and recovery so SDK snapshots remain available across application restarts.
Introduction
SOASAP SDKs evaluate flags from an in-memory snapshot. Where supported, the latest successfully synchronized snapshot can also be written to persistent local storage.
The persistent cache allows an SDK to restore its last known configuration after process restarts, container restarts, host reboots, rolling deployments, and temporary loss of connectivity to SOASAP Cloud.
A production cache strategy defines:
- where the cache is stored
- who can read and write it
- how long it survives
- whether multiple instances share it
- how corruption is handled
- when it should be cleared
- how cache failures are monitored
This page covers production storage design. It does not replace the Persistent Cache architecture page and does not describe a distributed cache, Redis, or an application database.
Cache responsibilities
The cache provides:
- restoration of the last known snapshot
- faster restart behavior
- startup resilience during network outages
- continuity during container or process replacement
- reduced dependence on the first synchronization round-trip
The cache does not provide:
- authoritative configuration
- cross-instance coordination
- distributed consensus
- real-time synchronization
- request-time flag evaluation
- permanent configuration history
- backup of the SOASAP control plane
Cache lifecycle
On first start, no local snapshot exists. Evaluation uses code-defined defaults until synchronization succeeds. After a successful sync, the SDK persists the snapshot where cache is configured.
On later restarts, the SDK restores the persisted snapshot into memory, then reconnects and refreshes when the control plane is reachable. The cache represents the most recent snapshot that the SDK successfully persisted. It may be older than the latest configuration in SOASAP Cloud.
Choosing a cache location
Use a dedicated writable directory owned by the application service. The directory should:
- be writable by the application process
- not be shared with unrelated services
- survive ordinary process restarts
- have predictable lifecycle behavior
- have sufficient local storage
- be included in operational monitoring
- avoid temporary-system cleanup where persistence is required
Recommended conceptual layout:
/application-data/
└── soasap/
└── cache/
The exact path depends on the operating system, runtime, SDK, deployment platform, and organizational standards. Do not assume one universal filesystem path across all hosts.
Cache path requirements
A production cache path should have these properties:
Writable
The SDK process must be able to create and replace cache files.
Private to the service
Unrelated services should not use the same cache location.
Stable
The path should not change unexpectedly between ordinary restarts.
Predictable
Operators should know when the directory is preserved or deleted.
Observable
Permission, capacity, and restoration failures should be detectable.
Appropriately durable
The storage lifetime should match the deployment model.
Filesystem permissions
Use the minimum permissions necessary for the application process.
Recommended principles:
- run the application as a non-root user
- grant write access only to the cache directory
- avoid world-writable directories
- prevent unrelated users or services from modifying the cache
- keep directory ownership consistent across deployments
- verify permissions during startup or deployment validation
- treat permission changes as production configuration changes
Potential symptoms of incorrect permissions:
- cache file is never created
- cache writes fail
- cache cannot be restored after restart
- the SDK always performs a cold start
- stale files cannot be replaced
- one deployment can read files but the next cannot
Exact Unix permission bits depend on the host and SDK packaging. Prefer validating the runtime identity can create, replace, and read the cache rather than copying a fixed mode from another service.
Single-instance cache design
For a single application instance, use one dedicated cache location for that instance.
Benefits:
- simple ownership
- predictable writes
- no file contention
- clear lifecycle
- straightforward recovery
This is the preferred model when each application instance has its own local filesystem or mounted volume.
Multi-instance cache design
Each application instance should generally maintain its own cache.
Why isolated caches:
- each SDK has its own synchronization lifecycle
- each process restores independently
- local cache avoids cross-process file contention
- one damaged cache does not affect the entire fleet
- recovery remains isolated per instance
Risks of shared writable cache storage:
- race conditions
- partially written files
- lock contention
- one instance overwriting another instance’s state
- platform-specific file-locking differences
- larger blast radius during corruption
Containers
A container filesystem may be ephemeral. If the cache is written only inside the container layer:
- it may survive a process restart inside the same container
- it may disappear when the container is replaced
- it may disappear during rescheduling
- it may not survive a new image deployment
Ephemeral container cache
Use when:
- cold starts are acceptable
- explicit defaults are sufficient
- the application can synchronize immediately
- storage simplicity is preferred
Mounted persistent cache
Use when:
- restart resilience is important
- the application may restart during a network outage
- reducing cold-start dependency is required
Use a dedicated mounted directory rather than the application image filesystem.
Kubernetes
Production considerations for Kubernetes storage models:
emptyDir
- shared across containers in the same Pod
- survives application-container restart
- removed when the Pod is deleted
- does not survive rescheduling to a new Pod
Suitable when process restart durability is sufficient and full Pod replacement may perform a cold start.
PersistentVolumeClaim
- may survive Pod replacement
- storage lifecycle depends on the volume and reclaim policy
- requires deliberate access-mode and ownership configuration
Suitable when snapshot restoration after Pod replacement is required and restart resilience during a network outage is important.
Node-local storage
- tied to a node
- may be lost when rescheduled
- may require operational cleanup
- can create uneven behavior across nodes
StatefulSets are an option when stable per-replica storage is already part of the application architecture. They are not required for ordinary SOASAP usage.
Docker and container orchestrators
For Docker and similar platforms, mount a dedicated writable volume when cache persistence across container replacement is required.
Operational considerations:
- volume ownership must match the container user
- read-only root filesystems require a separate writable mount
- image rebuilds do not automatically remove external volumes
- old cache data may survive longer than expected
- cleanup must be intentional
Virtual machines and bare-metal hosts
On long-lived hosts, use an application-data directory rather than the source-code directory, the deployment artifact directory, the current working directory, a temporary directory, or a user’s home directory for system services.
The cache should survive:
- application restarts
- service-manager restarts
- ordinary deployments
- host reboots, when required by the operational model
Also account for:
- service account ownership
- deployment-tool behavior
- disk cleanup policies
- host replacement
- backup and restore expectations
The cache generally does not need to be included in disaster-recovery backups because SOASAP Cloud remains authoritative. Restoring it may still improve startup behavior during simultaneous control-plane or network failure.
Serverless and ephemeral runtimes
Some serverless and edge runtimes provide only temporary local storage. In these environments:
- cache lifetime may be limited to one warm runtime
- storage may disappear between invocations or instances
- multiple instances cannot assume shared local state
- persistent cache benefits may be reduced
Recommend:
- always define explicit defaults
- do not assume local cache survives instance replacement
- rely on non-blocking synchronization
- treat cache restoration as an optimization where supported
- verify the platform’s storage guarantees
Do not introduce a remote database as a generic cache replacement unless an SDK explicitly supports that pattern.
Cache durability levels
| Storage Model | Survives Process Restart | Survives Container Replacement | Survives Host Replacement | Typical Use |
|---|---|---|---|---|
| Process-local temporary directory | Usually no | No | No | Development or intentionally ephemeral starts |
| Container writable layer | Often yes within the same container | Usually no | No | Simple containers where cold start is acceptable |
| Pod emptyDir | Yes within the Pod | No across Pod replacement | No | Kubernetes process-restart durability |
| Local host application-data directory | Yes | Depends on how containers are mounted | No | VM and bare-metal services |
| Dedicated container volume | Yes | Often yes when volume is retained | Depends on volume binding | Docker and orchestrated containers |
| Persistent Kubernetes volume | Yes | Often yes, subject to reclaim and identity | Depends on storage class and binding | Pod replacement resilience |
| Platform-managed persistent application storage | Yes | Usually yes within platform guarantees | Depends on platform | Managed hosts with durable app data |
Exact survival behavior depends on the platform, mount configuration, and reclaim policy.
Cache and deployments
In-place deployment
The cache may remain available if the data directory is outside the replaced application artifacts.
Rolling deployment
New instances may have:
- restored cache
- empty cache
- cache from a previous instance identity
depending on the storage model.
Immutable image deployment
The image should not contain a runtime-generated cache. Use a writable runtime mount when persistence is needed.
Blue/green deployment
Each environment should normally maintain separate cache storage. Do not share cache paths across blue and green deployments unless explicitly supported and operationally justified. Independent caches reduce cross-deployment contamination.
When cache should survive
Preserve cache across:
- routine process restarts
- application crashes
- container restarts
- host reboots where practical
- rolling replacements when restart resilience is required
- temporary control-plane outages
A surviving cache allows immediate restoration of the last known snapshot.
When cache should be cleared
Cache deletion should be intentional, not routine. Reasonable cases include:
- confirmed corruption
- cache format incompatibility after an SDK change, when documented
- switching to a different SOASAP environment
- changing application identity or API key scope
- security incident requiring local state removal
- troubleshooting under controlled conditions
- intentional clean-room deployment
- decommissioning the service
Clear only the affected service or instance cache rather than deleting all caches across the fleet.
Cache identity and environment isolation
Caches must not be reused across unrelated organizations, projects, environments, services, API keys, or application identities.
Risks of sharing cache storage across environments:
- staging configuration restored in production
- production configuration exposed to development
- confusing incident diagnostics
- incorrect values during startup
- larger security blast radius
Derive cache separation from deployment configuration, not from manual operator memory. See Security.
API key rotation and cache behavior
API key rotation changes synchronization credentials. Operators should consider whether the existing cache remains appropriate for the same organization, project, environment, and service.
- If the new key targets the same configuration scope, retaining cache may be reasonable where supported.
- If the key targets a different environment or project, use a separate cache location or clear the previous cache.
Do not assume automatic key-to-cache validation unless the SDK documents it. Test rotation behavior in staging.
Cache writes
Snapshot persistence happens outside the flag evaluation hot path.
SDKs may debounce or batch writes to reduce filesystem activity. Exact write timing depends on the SDK and should not be assumed from this page.
Operational implications:
- the cache may briefly lag behind the in-memory snapshot
- an abrupt process termination may leave the previously persisted snapshot
- write failure does not necessarily stop local evaluation
- disk performance should not affect each flag read
Atomicity and partial writes
A robust cache implementation should avoid exposing partially written state during restoration. Application operators should still plan for interrupted writes, host crashes, full disks, filesystem errors, abrupt container termination, and manual file modification.
If a cache cannot be validated or restored, the SDK should avoid treating corrupted state as valid and should fall back to defaults until synchronization succeeds. Exact validation behavior may vary by SDK; confirm details in the platform documentation.
Cache corruption
Possible causes:
- interrupted writes
- filesystem damage
- manual modification
- incompatible file format
- storage-driver issues
- disk corruption
- multiple processes writing the same file
- incomplete restore from a backup or volume snapshot
Possible symptoms:
- cache restoration warning
- application starts with defaults
- snapshot is not available after restart
- repeated parsing or validation errors
- synchronization works but cache cannot be rewritten
Recommended recovery sequence:
- Confirm that the application can still evaluate using memory or defaults.
- Record the cache error and affected path.
- Verify disk space and permissions.
- Stop the affected instance if required.
- Delete or quarantine only the affected cache.
- Restart the instance.
- Allow a clean synchronization.
- Verify that a new cache is written.
- Restart again in staging or a controlled instance to confirm restoration.
Deleting a corrupted cache forces a clean synchronization but temporarily removes offline restart protection.
Cache not restored
When a cache is not restored, check:
- whether the configured path is correct
- whether the file exists
- whether the runtime user can read it
- whether the directory is mounted in the new instance
- whether deployment replaced the directory
- whether the API key or environment changed
- whether the cache is corrupted
- whether the SDK version supports the cache format
- whether the previous process successfully wrote a snapshot
- whether storage was ephemeral
- whether startup logs report a restoration failure
For focused troubleshooting, see Cache Not Restored.
Disk-full and storage failure
Operational risks:
- cache updates cannot be persisted
- the current process may continue evaluating from memory
- a later restart may restore an older snapshot or no snapshot
- unrelated application writes may also fail
Recommended response:
- alert on low disk capacity
- identify the failing volume
- preserve application availability
- restore writable capacity
- verify a new snapshot is persisted
- test restoration after remediation
Cache security
Treat cache files as application configuration data. They may contain flag keys, flag values, environment configuration, and snapshot metadata.
Security recommendations:
- restrict filesystem access
- do not expose cache directories through static file servers
- do not commit cache files to source control
- do not include runtime cache in container images
- avoid placing cache files in publicly readable shared folders
- apply host or volume encryption where required by organizational policy
- include cache locations in incident-response and decommissioning procedures
- separate cache paths by environment
Feature flag values should not be treated as a secret-management system. Confirm with SDK documentation whether a given cache format contains any credentials or sensitive payloads.
Backup and restore
SOASAP Cloud remains the source of truth, so cache backups are normally not required for configuration recovery. A backup may preserve startup continuity, but it can also restore stale state.
Advantages:
- faster recovery during simultaneous network loss
- retained last-known snapshot after host replacement
Risks:
- restoring old configuration
- restoring the wrong environment’s cache
- expanding access to cached configuration
- complicating cache lifecycle
Do not treat cache backup as a substitute for control-plane durability. Where backups are used, validate environment identity and cache age after restore.
Cache retention and cleanup
A cache strategy should define:
- who owns cleanup
- when obsolete caches are removed
- how decommissioned services are handled
- whether old deployment slots retain cache
- how abandoned volumes are identified
- whether storage quotas apply
Recommend:
- remove caches for decommissioned services
- avoid fleet-wide scheduled deletion of active caches
- do not clear healthy caches during every deployment
- remove cache deliberately when environment identity changes
- monitor volume growth even if individual cache files are small
Observability
Recommend monitoring:
- cache restoration success
- cache restoration failure
- time of last successful cache write
- cache write failures
- cache file presence
- cache age
- filesystem permission errors
- disk capacity
- volume mount failures
- corrupted-cache events
- evaluations falling back to defaults after restart
- synchronization status after cache restoration
Synchronization health and cache health are related but distinct.
- SSE Connected + Cache Write Failed — current process is fresh, but restart durability is degraded.
- SSE Disconnected + Cache Restored — evaluation continues, but configuration freshness is degraded.
- No Cache + SSE Disconnected — only explicit defaults may be available.
Health and alert severity
Informational
- cache does not exist on the first application start
- cache is intentionally disabled
- cache was intentionally cleared
Warning
- cache write failed while in-memory evaluation continues
- restored snapshot is older than expected
- cache directory is approaching capacity
Critical or high priority
- application restarted during outage and no snapshot is available
- cache restoration fails across many instances
- permissions prevent all production replicas from persisting state
- wrong-environment cache is suspected
- cache storage failure accompanies synchronization loss
Exact alert severity depends on application requirements and acceptable stale behavior.
Failure-scenario table
| Scenario | Current Evaluation | Restart Behavior | Primary Risk | Recommended Action |
|---|---|---|---|---|
| Cache exists and is valid | In-memory snapshot | Restores last persisted snapshot | Restored state may be slightly stale | Keep monitoring sync and write health |
| Cache missing on first startup | Explicit defaults until sync | Cold start until first persist | Unsafe defaults | Ensure defaults and first sync succeed |
| Cache directory not writable | Usually continues from memory | No durable snapshot for next restart | Lost restart resilience | Fix permissions/ownership; verify write succeeds |
| Cache file not readable | Memory while process lives | Falls back to defaults or cold start | Unexpected defaults after restart | Fix read access; confirm restore path |
| Cache corrupted | Defaults until sync if restore fails | Invalid state must not be trusted | Silent bad config if validation is skipped | Quarantine/delete affected cache; resync |
| Disk full | Memory evaluation may continue | Older or missing snapshot on restart | Future restart durability and other writes | Free capacity; confirm new write |
| Cache stored in ephemeral container layer | Normal while container lives | Lost on container/Pod replacement | Cold starts on every replace | Mount durable volume if required |
| Volume not mounted | Defaults until sync | No restore | Assumed durability that does not exist | Fix mount; verify path in new instances |
| Shared cache written by multiple instances | Unpredictable | Possible partial or overwritten state | Corruption and contention | Isolate cache per active instance |
| Cache restored from the wrong environment | Wrong configuration until sync | Restores incorrect identity | Cross-environment contamination | Separate paths; clear wrong cache |
| Cache write fails during healthy synchronization | Current process remains fresh | Next restart may be stale or empty | Hidden restart-resilience degradation | Alert on write failure; remediate storage |
| Application restarts while SOASAP Cloud is unavailable | Restored cache if present; else defaults | Depends on prior persist success | Defaults-only if cache missing | Prefer durable cache; test blocked-network restart |
Production configuration checklist
- ✓ Use a dedicated cache directory per service — isolates ownership and recovery.
- ✓ Use an isolated cache per active SDK instance where practical — avoids concurrent-write risks.
- ✓ Ensure the runtime user can read and write the directory — deployment and runtime identities may differ.
- ✓ Choose storage with the required restart lifetime — process, container, Pod, and host replacement differ.
- ✓ Keep production and non-production caches separate — preserve environment isolation.
- ✓ Do not store the runtime cache inside an immutable image — cache is generated state.
- ✓ Monitor cache restoration and write failures — current evaluation may remain healthy while restart resilience is degraded.
- ✓ Keep explicit defaults for every flag read — cache availability is never guaranteed.
- ✓ Test restart behavior with networking blocked — verifies actual durability.
- ✓ Document cache-clearing procedures — deletion should be controlled and scoped.
- ✓ Verify cache behavior after SDK upgrades — format or configuration behavior may change per release notes.
- ✓ Avoid shared writable cache files across replicas — reduces corruption and contention risk.
Validation procedure
Validate cache behavior in staging before relying on it in production.
Test 1: Initial startup
Verify:
- no cache exists
- defaults are used where necessary
- synchronization succeeds
- a cache is created
Test 2: Normal restart
Verify:
- the cache is restored
- flags are available before synchronization completes
- synchronization refreshes the snapshot
Test 3: Restart without network
Verify:
- the cached snapshot restores
- the application becomes ready
- evaluation continues
- reconnection remains in the background
Test 4: Read-only cache directory
Verify:
- evaluation continues where possible
- cache-write failure is visible
- no request-time failure is introduced
- restart-resilience degradation is detected
Test 5: Missing volume
Verify:
- the application uses defaults
- health diagnostics report no restored snapshot
- synchronization rebuilds the cache after connectivity returns
Test 6: Corrupted cache
Verify:
- invalid data is not used silently
- the application falls back safely
- operators can delete or quarantine the cache
- a clean synchronization recreates it
Test 7: Rolling deployment
Verify:
- every replacement instance receives the intended storage
- cache ownership is correct
- no instance restores another environment’s state
- all instances synchronize after startup
Common misconceptions
"The cache is used for every flag evaluation."
False. Evaluation uses the in-memory snapshot.
"The cache is the source of truth."
False. SOASAP Cloud remains authoritative.
"A cache file should be shared by every replica."
Usually false. Each active instance should normally use isolated cache storage unless concurrent sharing is explicitly supported.
"A writable container filesystem is persistent storage."
Not necessarily. It may disappear when the container or Pod is replaced.
"Deleting the cache fixes every synchronization problem."
False. It removes local state but does not fix credentials, networking, DNS, or control-plane issues.
"If cache writes fail, flag evaluation immediately stops."
False. The running process may continue evaluating from memory, but future restart resilience is degraded.
"Persistent cache means the restored configuration is current."
False. The restored snapshot is the last successfully persisted state.
"Cache backups are required for SOASAP configuration recovery."
Usually false. The cache is a local durability layer, not the authoritative configuration store.
Relationship to other SOASAP concepts
| Concept | Relationship to cache strategy |
|---|---|
| Persistent Cache | Describes the architecture and startup role of cached snapshots |
| Offline Operation | Describes evaluation behavior when synchronization is unavailable |
| Non-Blocking Startup | Explains how cache and defaults allow startup without waiting for the network |
| High Availability | Explains why local evaluation isolates application traffic from the control plane |
| Outages | Explains incident behavior and recovery during synchronization loss |
| Default Values | Provide deterministic behavior when no valid cached or synchronized value exists |
| Cache Not Restored | Provides focused troubleshooting for restoration failures |
Related documentation
- Persistent Cache — architecture and startup role of cached snapshots
- Offline Operation — evaluation while sync is unavailable
- Non-Blocking Startup — readiness without waiting on first sync
- High Availability — availability boundaries and evaluation independence
- Outages — incident response during synchronization loss
- Scaling — multi-instance and fleet considerations
- Security — API keys, environments, and access boundaries
- Default Values — code-defined fallbacks
- Cache Not Restored — diagnosing restoration failures
- SSE Disconnected — sync interruptions while cache may remain valid
- Invalid API Key — credential failures that block sync and refresh
- SDK Documentation — platform-specific cache configuration