Storing first and reading current state from Stripe is the right call, and it matters most for anything that contacts the customer. If the sweeper picks up an invoice.payment_failed event an hour late, the retry may already have succeeded. Checking the invoice status before sending a failed-payment email saves a confusing message to someone who has already paid.