Why Can't We Just Publish the Event After SaveChanges()?
Because two successful operations do not become atomic merely by being adjacent in code.
The failure window
The database commit can succeed and the process can crash before publishing. The state now exists, but downstream services never hear about it.
Put intent in the transaction
Write the business record and an outbox record in one database transaction. A separate relay publishes pending outbox rows and marks them delivered.
What the pattern buys
The outbox turns an invisible in-memory intention into durable work that can be retried and observed.