---
title: "Comment by Paul Hartness on \"Credit packs + subscriptions in one wallet: expiring credits in SQLite without a cleanup cron\" | Hashnode"
description: "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 invoic"
url: "https://hashnode.com/posts/credit-packs-subscriptions-in-one-wallet-expiring-credits-in-sqlite-without-a-cleanup-cron/6adf4b7dcaa30cf051499f2c/comment/6ae1b675110fec1240b36075"
---

[Discussion](https://hashnode.com/posts/credit-packs-subscriptions-in-one-wallet-expiring-credits-in-sqlite-without-a-cleanup-cron/6adf4b7dcaa30cf051499f2c)

Comment [Credit packs + subscriptions in one wallet: expiring credits in SQLite without a cleanup cron](https://hashnode.com/posts/credit-packs-subscriptions-in-one-wallet-expiring-credits-in-sqlite-without-a-cleanup-cron/6adf4b7dcaa30cf051499f2c)

[Paul Hartness](https://hashnode.com/@retryfix)

[Oct 28](https://hashnode.com/posts/credit-packs-subscriptions-in-one-wallet-expiring-credits-in-sqlite-without-a-cleanup-cron/6adf4b7dcaa30cf051499f2c/comment/6ae1b675110fec1240b36075)

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.
