Save Pipelines Drawn as Graphs, Not Trigger Chains
“Make the save order visible and the failure localized - implicit trigger chains do neither.”
A small execution engine for multi-stage Salesforce Revenue Cloud (RCA) saves: declare dependencies, sort topologically, fail with a reason.
DAGRCADEPENDENCY GRAPHPIPELINES
Fixture saves run in declared order with cycles rejected at startup
What Made the Problem Difficult
Independent work, fixture models. Quoting-style saves couple calculation with persistence across several related entities, and the stages genuinely depend on each other. Implicit execution order turns every new rule into a regression risk.
Core Platform Constraint
Systemic FrictionChained handlers and flag-guarded triggers hide the order, allow cycles by accident, and spread one save across many partial writes - which then fail partially and reconcile manually.
- !Stages run in dependency order, stated explicitly in code
- !Upstream outputs feed downstream inputs without shared mutation
- !Any stage failure names the stage and preserves diagnostics
- !Adding a rule means adding a node, not editing five files
What System Was Designed
Each stage is a node with declared inputs, outputs, and dependencies. The engine topologically sorts the graph at startup (cycles fail fast with the offending edge named), threads an immutable context through execution, and defers persistence to a single bulk write at the end. Independent branches can run without waiting on each other.
Pivotal Architectural Choices
Key Architectural Decisions
Declared DAG vs. chained handlers
Implicit order is the leading cause of save bugs I have debugged.
- Trigger-handler frameworks with static flags
- One large procedural service
Order becomes reviewable. Cycles become compile-time errors. Orchestration stays separate from business rules.
Immutable context vs. shared mutable records
Shared mutation across stages produces action-at-a-distance bugs.
- Global static state
- In-place record mutation
Stages become unit-testable in isolation, and the audit of a failed save reads like a trace.
What Was Actually Built
Modeled stages as an adjacency-list graph with a fluent builder for registration.
Implemented Kahn's topological sort with cycle reporting that names the edge, not just the failure.
Carried an immutable execution context with per-stage diagnostics throughout.
Deferred writes to one bulk persistence step with heap-conscious DTOs in the study model.
Added per-node error boundaries so a tax-rule failure never masquerades as a persistence failure.
Deliberate Architectural Compromises
Trade-offs & Mitigations
⚖Graph ceremony vs. scripting speed
No cyclic saves by construction; new rules slot in safely.
Engineers declare nodes instead of writing inline steps.
A small builder API keeps registration to a few lines per stage.
⚖Deferred bulk write vs. incremental writes
One atomic write; no partial-commit cleanup.
Modifications accumulate in memory during the run.
Lightweight DTOs and explicit heap awareness in long pipelines.
Verified Outcomes
Fixture saves run in declared order with cycles rejected at startup
New calculation stages add without touching existing nodes in the study model
Failed saves identify the stage, its inputs, and the rule that rejected them
Calculation stays decoupled from persistence throughout
System Schematic & Data Flow
Ingress normalizes once, calculations fan out, persistence commits once - in sorted order.
Text alternative for screen readers: Architecture flow: Node A: Ingress Normalization to Node B: Line Calculation via Dependency Edge 01; Node A: Ingress Normalization to Node C: Tax Resolution via Dependency Edge 02; Node B: Line Calculation to Node D: Atomic Persistence via Calculated Lines Join; Node C: Tax Resolution to Node D: Atomic Persistence via Surcharges Join
Architectural Conclusion
“A save workflow you can draw is a save workflow you can reason about - and fix at 2am without fear.”
- •Implicit execution order is the most expensive kind of technical debt in record-heavy systems.
- •Explicit graphs turn save logic from archaeology into reading.