Middle · Trace · Fault-tested atomic outbox persistence

Portable .NET9 console only: predict every printed line and explain how the accepted immutable bundle and rejected quantity produce the three output lines. State which real HTTP, SQL or infrastructure guarantee this program does not test.

Think through your answer before opening the explanation.

Production engineering

using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;

Draft? Build(int quantity)=>quantity is >=1 and <=10 ? new Draft(quantity,"order:"+quantity) : null;
var draft=Build(2)!; Console.WriteLine("quantity:"+draft.Quantity); Console.WriteLine("event:"+draft.Event); Console.WriteLine("invalid rejected:"+(Build(0) is null));
record Draft(int Quantity,string Event);
Reveal answer and reasoning

Build accepts quantity two and creates a Draft containing that integer and the description order:2. The console therefore prints quantity:2 and event:order:2. Calling Build with zero returns null, so the final line is invalid rejected:True. These fields coexist in one ordinary record; the program performs no transaction, publication or durable write. It does not prove that two independent collections would update atomically under failure.

Its value is a deterministic statement of the accepted domain facts that the external persistence operation must later commit together or leave absent together.

The real failed POST inserts an order and outbox row inside one SQLite transaction, then deliberately rolls back and returns503. A fresh counts request observes zero orders and zero outbox rows. The valid POST then commits and returns201, after which both counts are one. Repeating the existing identity is an explicit conflict rather than a second order. These checks establish the tested local storage boundary and its rejection behavior.

A nonempty outbox table still means pending intent; nothing in this endpoint establishes that a remote broker accepted a publication or that a consumer executed an effect.

What a strong answer covers

  • The portable record groups quantity2 with event order:2; it does not execute SQL.
  • Actual pre-commit failure leaves orders0/outbox0; valid commit leaves1/1.
  • Persisted publication intent and external delivery have separate failure boundaries.

Common pitfall

Equating a committed outbox row with broker acceptance or exactly-once consumer execution.

Follow-up questions

  1. What state appears if business and event rows use separate commits?
  2. How does a lost acknowledgment after remote delivery affect replay?

Self-review

Choose what to revisit. These marks are your own assessment and are separate from lesson completion.

Primary references

Open lesson and code ↗

← All interview questions