# How the Reservation-Based Generation Flow Prevents Credit Loss in Awesome GPT Image 2

> Learn how Awesome GPT Image 2's reservation-based generation flow prevents credit loss by pending, finalizing, or refunding credits, ensuring you only pay for successful generations.

- Repository: [苍何/awesome-gpt-image-2](https://github.com/freestylefly/awesome-gpt-image-2)
- Tags: internals
- Published: 2026-08-29

---

**The reservation-based generation flow prevents credit loss by holding credits in a pending state during image generation, then either finalizing the deduction upon success or automatically refunding the user upon failure.**

The `freestylefly/awesome-gpt-image-2` repository implements a transactional safety mechanism that ensures users never lose credits for failed image generations. By wrapping every request in a database-backed reservation lifecycle, the system guarantees that **free-generation quotas** and **credit balances** are only permanently consumed when the upstream image model successfully returns a result.

## The Four-Step Reservation Lifecycle

The application orchestrates every generation request through a strict `reserve → generate → complete/release` workflow implemented in [`api/generate-image.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generate-image.js) and enforced by PostgreSQL stored procedures.

### Step 1: Reserve

Before calling any external image service, the handler invokes `reserveGeneration` (or `reserveCreditGeneration` for administrators). This function executes the `reserve_generation_usage` stored procedure, which:

- Creates a row in the `generation_reservations` table with `status = 'pending'`
- Provisionaly decrements the user's available free generations or holds the required credit amount
- Returns a unique `reservationId` that tracks this specific request

According to the source code in [`supabase/migrations/202605090001_user_credits.sql`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/supabase/migrations/202605090001_user_credits.sql), this reservation acts as a **lock** on the resources, preventing race conditions where multiple simultaneous requests might overdraft the user's balance.

### Step 2: Generate

Only after obtaining a valid reservation does the handler call the external `generateImage` service. This ordering is critical: if the upstream service fails, times out, or returns a 429 error, the reservation record persists in the database, enabling a full rollback.

### Step 3: Complete on Success

When the image generation succeeds, the handler calls `completeReservation`, which executes the `complete_generation_reservation` stored procedure (lines 74-88 in the migrations file). This procedure:

- Verifies the reservation status is still `pending`
- Updates the status to `succeeded`
- Records the completion timestamp

**No credit adjustments occur during completion.** The deduction was already applied during the reserve step; completing the reservation simply finalizes the transaction, preventing double-charging or duplicate refunds.

### Step 4: Release on Failure

If any error occurs during generation, the handler invokes `releaseReservation`, triggering the `release_generation_reservation` stored procedure (lines 92-145). This critical rollback logic:

- Checks that the reservation remains in `pending` status to prevent double-refunds
- For free generations: increments `free_generations_used` to restore the quota
- For credit payments: adds the credit amount back to `credit_balance` and records a refund transaction
- Marks the reservation as `failed` with an error code

By explicitly rolling back provisional changes in the database, the system ensures **zero credit loss** for failed requests.

## Key Implementation Details

### Database Schema and Stored Procedures

The `generation_reservations` table serves as the source of truth for all in-flight requests. Three core stored procedures manage the state transitions:

- **`reserve_generation_usage`**: Atomically checks balance, creates the pending reservation, and holds resources
- **`complete_generation_reservation`**: Marks successful completions without modifying credit totals
- **`release_generation_reservation`**: Handles the refund logic by restoring `free_generations_used` or `credit_balance`

These procedures are defined in [`supabase/migrations/202605090001_user_credits.sql`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/supabase/migrations/202605090001_user_credits.sql) and enforce consistency at the database level, independent of application logic.

### API Handler Logic

The [`api/generate-image.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generate-image.js) file implements the orchestration layer:

- **Lines 59-80**: Reserve the generation before any external calls
- **Lines 21-23**: Complete the reservation after successful image retrieval
- **Lines 36-38**: Release the reservation and trigger refunds on any caught exceptions

This structure ensures that even if the Node.js process crashes between the external API call and the finalization step, the database maintains a record of the pending reservation that can be cleaned up by background jobs or investigated for manual refund.

## Code Examples

### Reserving a Generation

```javascript
// api/generate-image.js
const reservation = auth.profile.isSuperAdmin
  ? await reserveCreditGeneration(auth.client, auth.user.id, caseId, prompt)
  : await reserveGeneration(auth.client, auth.user.id, caseId, prompt);

// reserveGeneration calls the Supabase RPC:
// SELECT * FROM reserve_generation_usage(user_id, case_id, prompt)

```

### Completing a Successful Reservation

```javascript
// After successful image generation
await completeReservation(auth.client, reservation.reservationId);

// Executes: SELECT complete_generation_reservation(reservation_id)
// Updates status from 'pending' to 'succeeded'

```

### Releasing and Refunding on Failure

```javascript
// When upstream returns 429 or other errors
const errorCode = error?.status === 429 ? 'UPSTREAM_BUSY' : 'GENERATION_FAILED';
await releaseReservation(auth.client, reservation.reservationId, errorCode);

// Executes release_generation_reservation, which:
// 1. Restores free_generations_used OR adds credits back to credit_balance
// 2. Inserts a refund transaction record
// 3. Sets status = 'failed'

```

## Summary

- The **reservation pattern** creates a pending transaction state before consuming external resources
- **Database-level stored procedures** enforce atomic operations for reserving, completing, and releasing credits
- **Automatic rollback** via `release_generation_reservation` restores both free-generation quotas and credit balances when upstream services fail
- The implementation in [`api/generate-image.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generate-image.js) ensures every code path either completes or releases the reservation, eliminating orphaned transactions

## Frequently Asked Questions

### What happens if the server crashes during image generation?

The reservation row remains in the `generation_reservations` table with `status = 'pending'`. Because the credit was already deducted during the reserve step but the generation never completed, administrators can identify these stale reservations and manually trigger refunds, or a background cleanup job can automatically release reservations older than a specific threshold.

### How does the system prevent double-charging users?

The `complete_generation_reservation` procedure only updates the reservation status without touching the `credit_balance` or `free_generations_used` columns. Since the deduction occurred atomically during the reserve step, and completion merely changes a status flag, there is no code path that subtracts credits twice for a single reservation.

### Can administrators bypass the free-generation quota?

Yes. The codebase provides `reserveCreditGeneration` specifically for super administrators (lines 59-80 in [`api/generate-image.js`](https://github.com/freestylefly/awesome-gpt-image-2/blob/main/api/generate-image.js)). This function forces credit usage even when free generations are available, ensuring that admin usage is always logged and billed against credits rather than consuming the limited free tier.

### What error codes trigger a refund?

Any exception caught in the generation handler triggers `releaseReservation`. Specifically, HTTP 429 responses map to the `UPSTREAM_BUSY` error code, while all other failures use `GENERATION_FAILED`. Both codes result in identical refund behavior through the `release_generation_reservation` stored procedure.