Outbid Notification Service
Relevant source files
The following files were used as context for generating this wiki page:
The Outbid Notification Service sends transactional emails to previous sponsors when a new confirmed payment replaces their published advertisement. It utilizes Cloudflare Email Service for delivery and coordinates with the Auction Durable Object to ensure reliable, once-only notification processing.
Sources: apps/website/OUTBID-NOTIFICATIONS.md:3-5, apps/website/worker/auction.ts:389-395
Architecture and Data Flow
The service operates within a Cloudflare Worker using a Durable Object for state management. When a bid is successfully fulfilled through Stripe, the system enqueues a notification in a local SQLite table. A background alarm process then attempts delivery.
The system commits ownership changes and notification rows in a single SQLite transaction to prevent duplicate queuing.
Sources: apps/website/OUTBID-NOTIFICATIONS.md:9-12, apps/website/worker/auction.ts:389-408
Email Enqueueing Logic
Notifications are only enqueued when a payment is confirmed. Unpaid checkouts or bids refunded before publication do not trigger emails. The service identifies the displaced owner using the email address provided during their original Stripe Checkout session.
Sources: apps/website/OUTBID-NOTIFICATIONS.md:9-15, apps/website/worker/auction.ts:400-405
Data Schema
The service relies on the outbid_emails table within the Auction Durable Object's SQLite storage.
| Field | Type | Description |
|---|---|---|
previous_bid_id | TEXT | Primary Key. The ID of the displaced bid. |
replacement_bid_id | TEXT | The ID of the new winning bid. |
status | TEXT | Current state: pending, sent, failed, or skipped. |
attempts | INTEGER | Number of delivery attempts made. |
next_attempt_at | INTEGER | Timestamp for the next retry attempt. |
created_at | INTEGER | When the notification was enqueued. |
sent_at | INTEGER | When the email was successfully accepted by the provider. |
message_id | TEXT | The Cloudflare message ID for tracking. |
last_error | TEXT | The error code from the last failed attempt. |
Sources: apps/website/worker/auction.ts:47-53
Processing and Retries
The processOutbidEmails function handles the transmission of queued notifications.
- Selection: Selects up to 20
pendingrows wherenext_attempt_atis due. - Identity Verification: Retrieves the
buyer_emailfrom the previous and replacement bids. - Suppression: Skips the email if the same owner raised their own bid or has already regained the spot.
- Delivery: Sends the email via
this.env.EMAIL.send(). - Persistence: Updates the row status to
sentand records themessageId.
Sources: apps/website/worker/auction.ts:468-525, apps/website/OUTBID-NOTIFICATIONS.md:18-20
Error Handling
The service uses exponential backoff for retries, capped at one hour (3,600,000ms).
Email Construction
Emails are formatted as both HTML and plain text. The content includes the displaced placement details, the replacement bid amount, and a link to the current auction price for that spot.
Key Functions
outbidEmail(input): Generates the subject, HTML, and text content. It escapes advertiser text to prevent injection.checkoutEmail(session): Extracts and validates the email address from Stripe session data, ensuring it matches a standard email regex and does not exceed 254 characters.emailErrorCode(error): Normalizes error codes into a stable string format (e.g.,E_RECIPIENT_SUPPRESSED).
Sources: apps/website/worker/outbid-email.ts:3-13, apps/website/worker/outbid-email.ts:28-66, apps/website/tests/outbid-email.test.ts:11-30
Configuration and Operations
Environment Variables
| Variable | Scope | Description |
|---|---|---|
EMAIL | Binding | Cloudflare Email Service send binding. |
OUTBID_EMAIL_FROM | String | Verified sender address (e.g., updates@notify.thedrivingfly.com). |
OUTBID_EMAIL_TEST_TO | Secret | Recipient address for all Stripe test-mode notifications. |
Sources: apps/website/OUTBID-NOTIFICATIONS.md:32-45
Monitoring
Operators can monitor delivery via the Cloudflare Activity log or by querying the Durable Object SQLite storage directly. Logs include Outbid email accepted for successful provider handover and specific error codes for failures, but never recipient addresses.
Sources: apps/website/OUTBID-NOTIFICATIONS.md:52-60, apps/website/worker/auction.ts:522-524
Privacy and Security
The service treats buyer_email as private data. It is excluded from public snapshots, WebSocket messages, and artwork responses. The email address is only retrieved from Stripe's authoritative state (never the browser) and is stored in a private bids column.
Sources: apps/website/src/app/privacy/page.tsx:24-34, apps/website/OUTBID-NOTIFICATIONS.md:14-17, apps/website/worker/auction.ts:114-140
The Outbid Notification Service ensures that sponsors are promptly informed when their placements are replaced, facilitating ongoing engagement with the auction while maintaining strict data privacy and delivery reliability.