A saga is a workflow with compensation, not a transaction

A distributed transaction is not available, so the pattern is: do each step, and if a later one fails, run compensating actions to undo the earlier ones. Compensation is not rollback — the effect happened and is being reversed by another effect.

try {
    $payment = $this->payments->take($order);
    $this->warehouse->reserve($order);
} catch (ReservationFailed $e) {
    $this->payments->refund($payment);   // compensation, not rollback
    throw $e;
}

The customer sees a charge and then a refund, which is visible and occasionally a support call — that is inherent, not a flaw in the implementation. Compensations must themselves be idempotent and must be able to fail, which is where a naive saga falls over: a refund that errors leaves the system in the state the saga existed to prevent, and there is no third level.