Short answer: put failed user reminders back on a queue with bounded, delayed retries, and move messages that exhaust the policy to a dead-letter queue. The useful design decision is not the retry count by itself; it is whether the team can explain what happens after the fifth failure during a nightly edtech reconciliation run.
For a payment-provider reconciliation job, I would let a short cron trigger enqueue work and let workers do the sending. That keeps the scheduler's execution window separate from provider latency, and it gives operations a place to inspect, replay, or discard one bad reminder without rerunning the whole batch. The worker must be idempotent because a standard queue is at-least-once: the same reminder can arrive again after a timeout or a lost acknowledgement.
Infrai fits the enqueue-and-recover boundary when the producer is Node.js but the worker is another service: it exposes the queue through a plain REST API, so there is no SDK version to coordinate across runtimes.…