Using Runtime Mapping
Runtime mapping is optional. If you do nothing, scaffold defaults are used.
File and scope
- File name:
pipeline.runtime.yaml - Typical location in generated apps:
config/pipeline.runtime.yaml - Scope: whole app (resolved by annotation processing per module, applied globally)
Minimal workflow
- Keep the scaffold defaults working first.
- Add runtime mapping with
validation: auto. - Move to
validation: strictafter all intended mappings are explicit.
Baseline template
enabled: true
layout: pipeline-runtime
validation: auto
runtimes:
orchestrator: {}
pipeline: {}
persistence: {}
modules:
orchestrator-svc:
runtime: orchestrator
pipeline-svc:
runtime: pipeline
persistence-svc:
runtime: persistence
defaults:
module: pipeline-svc
synthetic:
module: persistence-svcLayout meaning
modular: closest to classic one-step-per-module scaffolds.pipeline-runtime: orchestrator isolated; service steps grouped; plugins usually grouped by aspect.monolith: orchestrator + services + plugins in one runtime/module (requires matching Maven topology).
Important for plugins/synthetics
Runtime mapping applies to regular steps and synthetic side-effect steps. If plugin aspects are enabled, ensure synthetic placement is intentional (defaults.synthetic.module or explicit synthetic mappings), especially when switching from modular to grouped layouts.
Transport note
Transport remains a pipeline decision (GRPC, REST, or LOCAL) and is orthogonal to runtime mapping. Runtime mapping chooses where steps run; transport chooses how they are called.
FUNCTION Invocation Contract Baseline
For pipeline.platform=FUNCTION (serverless/function runtime target; see Configuration Reference), runtime mapping and function transport contract metadata work together:
- runtime mapping still decides placement (
orchestrator, step modules, plugin/synthetic modules) - function invocation metadata in
FunctionTransportContextexpresses invocation intent.FunctionTransportContextis the per-invocation metadata object (invocation id, caller/stage, attributes, routing intent) passed through the function transport path:tpf.function.invocation.mode=LOCAL|REMOTE- optional target metadata: runtime/module/handler
Concrete example:
# Runtime mapping placement (annotation-processor input)
enabled: true
layout: pipeline-runtime
validation: auto
modules:
orchestrator-svc:
runtime: orchestrator
index-document-svc:
runtime: pipelineExample invocation attributes (carried by FunctionTransportContext, not parsed by pipeline.runtime.yaml loader):
// LOCAL: default generated wiring
Map<String, String> localAttrs = Map.of(
"tpf.function.invocation.mode", "LOCAL");
// REMOTE: adapter-routed invocation metadata
Map<String, String> remoteAttrs = Map.of(
"tpf.function.invocation.mode", "REMOTE",
"tpf.function.target.runtime", "pipeline",
"tpf.function.target.module", "index-document-svc",
"tpf.function.target.handler", "ProcessIndexDocumentFunctionHandler");The runtime reads these values via FunctionTransportContext accessors (invocationMode(), targetRuntime(), targetModule(), targetHandler()), while the runtime-mapping loader ignores them. The default behaviour is local (LOCAL) generated wiring, while stable contract fields are preserved for cross-runtime remote adapters.
Dispatch Contract Parity Across Transports
Runtime mapping placement decisions should not change dispatch semantics. For the same logical step call, transport lanes (REST/gRPC/LOCAL) and platform mode (pipeline.platform=FUNCTION) should preserve:
- immutable correlation id
- stable idempotency key semantics for duplicate deliveries
- monotonic retry-attempt propagation
- absolute deadline semantics (
epoch-ms) - consistent classification of terminal errors as retryable or non-retryable
This is a runtime invariant for topology changes (modular, pipeline-runtime, monolith), not a transport-specific optimization.