Data Persistence
The data persistence effect stores a Metadata record for every train execution. Each record captures the train name, state, timing, inputs/outputs, and failure details. See Metadata for the full field breakdown.
Two backends are available: PostgreSQL for production and InMemory for testing. Both implement the same IDataContext interface, so your train code doesn't change between them.
PostgreSQL
dotnet add package Trax.Effect.Data.Postgresservices.AddTrax(trax => trax
.AddEffects(effects => effects
.UsePostgres("Host=localhost;Database=app;Username=postgres;Password=pass")
)
);On first startup, the Postgres provider runs automatic migrations to create the trax schema and its tables (metadata, logs, manifests, dead_letters). Subsequent startups apply any pending migrations.
The provider uses Entity Framework Core with Npgsql. Train states and dead letter statuses are mapped to PostgreSQL enum types. Input and output fields use jsonb columns. All timestamps are stored in UTC.
What Gets Persisted
Every ServiceTrain execution creates a Metadata row:
| Field | Description |
|---|---|
Name | Train class name |
TrainState | Pending -> InProgress -> Completed or Failed |
StartTime / EndTime | Execution duration |
Input / Output | Serialized JSON (requires Parameter Effect) |
FailureJunction | Which junction threw |
FailureException | Exception type |
FailureReason | Error message |
StackTrace | Full stack trace on failure |
ParentId | Links to parent train for nested trains |
ManifestId | Links to scheduling manifest |
Without the Parameter Effect, the Input and Output columns are null — metadata is still persisted, but without the serialized request/response data.
InMemory
dotnet add package Trax.Effect.Data.InMemoryservices.AddTrax(trax => trax
.AddEffects(effects => effects
.UseInMemory()
)
);Uses Entity Framework Core's in-memory provider. No connection string, no migrations, no external dependencies. Data is lost when the process exits.
Use this for unit tests and integration tests where you want metadata tracking without a database:
var services = new ServiceCollection();
services.AddTrax(trax => trax
.AddEffects(effects => effects
.UseInMemory()
)
.AddMediator(typeof(MyTrain).Assembly)
);
var provider = services.BuildServiceProvider();
var context = provider.GetRequiredService<IDataContext>();
// Run a train, then query metadata
var metadata = await context.Metadatas.FirstOrDefaultAsync();
Assert.Equal(TrainState.Completed, metadata.TrainState);DataContext Logging
Logs the SQL queries that EF Core generates. Useful when debugging persistence issues or inspecting what the data provider is doing:
services.AddTrax(trax => trax
.AddEffects(effects => effects
.UsePostgres(connectionString)
.AddDataContextLogging(minimumLogLevel: LogLevel.Information)
)
);Log levels can also be changed at runtime via the Dashboard's Server Settings page. The optional blacklist parameter filters out noisy namespaces:
.AddDataContextLogging(
minimumLogLevel: LogLevel.Debug,
blacklist: ["Microsoft.EntityFrameworkCore.Infrastructure.*"]
)Blacklist entries support exact matches and wildcard patterns.
SDK Reference
> UsePostgres | UseInMemory | SaveTrainParameters | AddDataContextLogging