Using the invoice ID as the primary key is a neat way to make duplicate invoice.paid events harmless. One path I'd add: a renewal whose payment fails. No invoice.paid means no new credit row, which is correct, but the user just wakes up with zero credits and no idea why, so a short note on invoice.payment_failed with a card-update link saves you a confused support email.