Persistence
By default, MicroStack stores all state in memory. When the process stops, everything is gone. For development workflows that need state across restarts, MicroStack supports optional JSON file persistence.
Enabling Persistence
Set the PERSIST_STATE environment variable:
# Docker
docker run -e PERSIST_STATE=1 -v ./state:/tmp/microstack-state -p 4566:4566 ghcr.io/damianh/microstack:latest
# Direct
PERSIST_STATE=1 dotnet run --project src/MicroStack/MicroStack.csprojHow It Works
The StatePersistence class (src/MicroStack/Internal/StatePersistence.cs) manages the lifecycle:
Save (on shutdown)
- The ASP.NET Core
IHostApplicationLifetime.ApplicationStoppingevent triggersSaveAll(). - For each registered service handler, calls
handler.GetState(). - If the handler returns non-null state, serializes it as JSON to
{STATE_DIR}/{serviceName}.json. - Uses atomic writes: writes to a
.tmpfile first, thenFile.Movewith overwrite. This prevents corruption if the process is killed mid-write.
Restore (on startup)
- After building the app and registering all handlers, calls
persistence.RestoreAll(). - For each handler, checks if
{STATE_DIR}/{serviceName}.jsonexists. - If found, deserializes the JSON and calls
handler.RestoreState(data). - Handlers populate their in-memory collections from the deserialized data.
Reset
The POST /_microstack/reset endpoint calls:
registry.ResetAll()— clears all in-memory state.persistence.DeleteAll()— deletes all.jsonfiles inSTATE_DIR.
State Directory
| Variable | Default | Description |
|---|---|---|
STATE_DIR |
<temp>/microstack-state |
Directory where state files are written |
Each service gets its own file:
microstack-state/
sqs.json
dynamodb.json
s3.json
sns.json
...
Handler State Contract
Every IServiceHandler implements two methods:
object? GetState();
void RestoreState(object data);GetState()returns a serializable object representing the handler's current state, ornullif there's nothing to persist.RestoreState(object data)receives the deserialized JSON (asSystem.Text.Jsonobject trees) and rebuilds in-memory collections.
Handlers use AccountScopedDictionary<TKey, TValue>.ToRaw() and .FromRaw() to serialize/deserialize their account-scoped collections, preserving account isolation across restarts.
S3 Object Persistence
S3 has a separate persistence mode via the S3_PERSIST or LOCALSTACK_PERSISTENCE environment variables. When enabled, S3 object data (blobs) are persisted to disk in addition to metadata. This is independent of the general PERSIST_STATE mechanism.
Error Handling
Persistence is best-effort:
- If saving a service's state fails, the error is logged and other services continue saving.
- If restoring a service's state fails, the error is logged and the service starts with empty state.
- If a temp file can't be deleted after a failed write, the error is silently ignored.
This ensures persistence issues never prevent MicroStack from starting or shutting down.
MicroStack