Metadata

Every train execution produces a metadata record. It captures everything about the run: when it started, what junctions it passed through, what it was carrying, and whether it completed or failed.

FieldTypeDescription
IdlongAuto-generated primary key
NamestringTrain name (canonical interface FullName)
ExternalIdstringGUID for external references
Executorstring?Assembly that ran the train
TrainStateTrainStatePending / InProgress / Completed / Failed / Cancelled
StartTimeDateTimeWhen the train started
EndTimeDateTime?When the train finished
Inputstring?Serialized input (jsonb)
Outputstring?Serialized output (jsonb)
FailureJunctionstring?Which junction failed
FailureExceptionstring?Exception type
FailureReasonstring?Error message
StackTracestring?Stack trace if failed
ParentIdlong?Links to parent metadata for nested trains
ManifestIdlong?Links to manifest for scheduled trains
ScheduledTimeDateTime?Scheduled execution time
CancellationRequestedboolCross-server cancellation flag
JunctionStartedAtDateTime?Current junction start timestamp (requires AddJunctionProgress)
CurrentlyRunningJunctionstring?Name of the currently running junction (requires AddJunctionProgress)
HostNamestring?Machine hostname where the train ran
HostEnvironmentstring?Environment type (lambda, ecs, kubernetes, server)
HostInstanceIdstring?Instance identifier (pod name, Lambda stream, etc.)
HostLabelsstring?User-provided labels as JSON (region, service, team)

The TrainState tracks the lifecycle: Pending -> InProgress -> Completed, Failed, or Cancelled. If a train fails, the metadata record captures the exception, stack trace, and which junction it happened at.

Failure Fields

When a junction throws, Trax captures structured context without modifying the original exception. The junction name, exception type, original message, and stack trace from the throw site are attached to the exception via Exception.Data["TrainExceptionData"]. When the train finishes, Metadata.AddException() reads this structured data and populates:

FieldSourceExample
FailureJunctionJunction class name where the throw occurred"ValidateInputJunction"
FailureExceptionException type short name"InvalidOperationException"
FailureReasonOriginal exception message (unmodified)"Input 'email' was null"
StackTraceStack trace from the original throw sitePoints to the junction's Run method

The original exception is rethrown to callers with its type, message, and stack trace intact. TrainExceptionData rides along in Exception.Data for any code that wants structured context (e.g., logging, monitoring).

Host Tracking

In distributed environments (Lambda, ECS, multiple servers), every metadata record captures where the train actually executed. Host information is auto-detected at startup and stamped on each execution. See Host Tracking for details on auto-detection, custom labels, and the builder API.

Nested Trains

A junction can dispatch another train mid-execution by injecting ITrainBus. Pass the current Metadata to the child train to link the executions. This creates a tree of metadata records you can query to trace execution across an entire network of trains.

See Mediator: Nested Trains for implementation details.

Execution Flow

For a diagram of the full ServiceTrain lifecycle, from client request through metadata initialization to SaveChanges, see Effect Architecture.