How to never pay a generative API twice: a durable task table, not a retrying job queue
The instant you might have been charged is not the provider's response, it is the moment before the request leaves your process. Write it to a row before the HTTP call and a dead worker becomes recoverable without guessing: nothing written means retry is safe, a saved request id means poll, and the gap between them needs a third terminal state.