Home → Documentation → Runtime → Mutations
Mutation Planning is responsible for transforming create, update, delete, upsert, connect, disconnect, and graph mutations into a deterministic execution graph. Unlike queries, mutations have ordering constraints, dependencies, transactional semantics, identity propagation, and conflict resolution. The Mutation Planner resolves these concerns before Runtime begins execution.
Runtime executes mutations.
The Mutation Planner understands mutations.
Mutation planning follows one rule:
Determine every dependency before execution begins.
Runtime should never discover ordering.
Runtime should never resolve dependencies.
Everything must already exist in the MutationPlan.
Mutation Request
↓
Planner
↓
Metadata Resolution
↓
Dependency Analysis
↓
Graph Analysis
↓
Ordering
↓
MutationPlan
Planning finishes before execution starts.
Queries are read operations.
Mutations change state.
Changing state introduces additional complexity:
The planner resolves all of these.
The Mutation Planner is responsible for:
It never executes SQL.
Runtime receives a completed MutationPlan.
Runtime performs:
MutationPlan
↓
SQL Generation
↓
Execution
↓
Materialization
Runtime assumes the plan is valid.
A MutationPlan is immutable.
Example:
MutationPlan
├── Operations
├── Dependencies
├── Graph Operations
├── Lookups
├── Identity References
├── Execution Order
└── Transaction Scope
Everything required for execution is already known.
Each mutation becomes an operation node.
Examples:
Insert
Update
Delete
Upsert
Lookup
Connect
Disconnect
Operations become vertices in an execution graph.
Mutations naturally form a graph.
Example:
Customer
↓
Order
↓
OrderItem
OrderItem cannot execute before Order.
Order cannot execute before Customer.
The planner computes this graph.
Dependencies are explicit.
Row 0
↓
Row 4
↓
Row 8
Runtime never discovers dependency order.
Generated identities become dependency references.
Example:
Customer.Id
↓
Order.CustomerId
Runtime copies values according to the plan.
It never searches for relationships.
References are represented explicitly.
Reference
Source Row
↓
Target Row
↓
Target Column
References remain immutable.
Lookups are planned separately.
Example:
Country
↓
Lookup
↓
CountryId
Runtime receives complete lookup instructions.
Upserts require conflict analysis.
Planner determines:
Runtime only serializes provider syntax.
Graph mutations extend dependency planning.
Example:
Customer
↓
Order
↓
OrderItem
↓
Product
Traversal order becomes execution order.
Execution order is determined through topological sorting.
Dependencies
↓
Topological Sort
↓
Execution Sequence
Runtime executes sequentially.
Cycles must be detected during planning.
Example:
A
↓
B
↓
A
Planner reports diagnostics.
Runtime never receives cyclic plans.
Conflict behavior becomes metadata.
Examples:
Do Nothing
Update
Replace
Merge
Providers translate conflict semantics.
Planner determines transactional scope.
Entire Mutation
↓
Single Transaction
Or
Nested Savepoints
Runtime coordinates transactions.
Graph merges become explicit operations.
Example:
Customer
↓
CustomerCustomerEdge
↓
Customer
Graph operations are independent from SQL generation.
Independent mutation branches can execute separately.
Example:
Customer
↓
Order A
↓
OrderItem A
Customer
↓
Order B
↓
OrderItem B
Planner identifies execution arms.
Future runtimes may parallelize them safely.
Planner consumes:
EntityMetadata
MutationMetadata
JoinMetadata
LookupMetadata
Runtime never performs metadata analysis.
Every mutation node receives a deterministic identifier.
Example:
m0
m1
m2
m3
Identifiers remain stable.
Planner identifies parameter sources.
Examples:
Runtime simply binds values.
Planner builds mutable graphs internally.
Runtime receives immutable graphs.
Builder
↓
MutationGraph
↓
MutationPlan
Mutation ends before execution begins.
Planning validates:
Invalid plans are rejected.
The same mutation always produces:
Determinism greatly improves testing.
Mutation planning ends at:
MutationPlan
SQL generation begins afterwards.
Providers should never perform dependency analysis.
Runtime executes according to the graph.
Node
↓
Dependencies Satisfied?
↓
Execute
↓
Propagate Identity
↓
Continue
Execution follows the plan exactly.
Materialization occurs after execution.
Generated materializers reconstruct:
No planning occurs.
Mutation planning should be tested independently.
Recommended tests:
Dependency Tests
↓
Identity Tests
↓
Lookup Tests
↓
Topological Order Tests
↓
Snapshot Tests
Runtime assumes planner correctness.
Mutation planning naturally supports Native AOT because it relies entirely on generated metadata and immutable models.
No runtime discovery or reflection is required.
Potential enhancements include:
Each enhancement should preserve Runtime simplicity.
Before adding mutation logic, ask:
If not, reconsider the design.
The Mutation Planner forms the boundary between mutation intent and mutation execution.
Transport
↓
Mutation Planner
↓
MutationPlan
↓
Runtime
↓
SQL Provider
↓
Database
Runtime becomes an execution engine rather than a mutation analyzer.
The Mutation Planning Architecture transforms mutation requests into immutable dependency graphs by resolving entity relationships, identity propagation, lookup operations, graph traversals, conflict semantics, and execution ordering before Runtime begins.
This design enables deterministic execution, simplified Runtime logic, provider-independent SQL generation, reliable transactional behavior, comprehensive testing, and full Native AOT compatibility while supporting increasingly sophisticated graph mutation scenarios.
| ← Previous: Queries | Next: Events → |