Where The Window Is

A team is moving off dual writes. Their first attempt:

def place_order(order):
    with db.transaction():
        db.execute("INSERT INTO orders (id, customer_id, total) VALUES (%s,%s,%s)", ...)
    # (1)
    with db.transaction():
        db.execute(
            "INSERT INTO outbox (id, aggregatetype, aggregateid, type, payload)"
            " VALUES (%s,'Order',%s,'OrderCreated',%s)", ...)
    # (2)

A separate log connector tails outbox and publishes each row to a topic. The process can be killed at (1) or (2). Which change removes the failure window, and why is the alternative worse?

One transaction writes the orders row and the outbox row, then a log connector publishes the outbox row handler one transaction INSERT orders INSERT outbox log connector topic
A

Keep the two transactions and have the handler publish to the topic directly after (2), so the event is out even if the connector is behind

B

Put both inserts in one transaction. A kill at (1) then rolls back the order along with the missing event, and a kill after the single commit loses nothing because the outbox row is already durable and the connector will publish it whenever the connector next runs

C

Keep the two transactions and wrap them in a try that deletes the order row if the outbox insert fails, so the two writes always end in the same state

D

Keep the two transactions but reverse them, inserting the outbox row first, so a kill at (1) leaves an event with no order and consumers can treat an unknown order id as a no-op