How the Dub Referral Sweep Process Works in Open SEO: A Complete Technical Guide

The Dub referral sweep process is a daily cron job that converts unpaid Autumn invoices from referred organizations into Dub sales events, ensuring referral commissions are captured even when real-time billing webhooks fail.

The Open SEO platform attributes partner-driven sign-ups to Dub through a resilient multi-step pipeline that culminates in a scheduled cron handler. When users sign up via Dub marketing links, the system tracks their journey from initial click through to paid invoice, using a combination of KV storage and API calls. The daily sweep acts as a critical fallback mechanism, catching renewal and top-up revenue that might be missed by the immediate webhook path.

Overview of the Referral Attribution Pipeline

The complete referral flow spans four distinct stages before reaching the daily cron sweep. First, signup events capture the Dub click ID and post lead events asynchronously. Second, each user session checks for referral pins and associates them with the user's founding organization. Third, real-time billing webhooks attempt immediate sale attribution. Finally, the daily cron sweep processes any remaining unpaid invoices that escaped the webhook trigger.

All referral logic resides in src/server/referrals/dub.ts, with the cron handler registered in src/server.ts and scheduled via wrangler.jsonc in the Cloudflare Workers configuration.

Step 1: Capturing Referrals on User Signup

When a new user registers, the system checks for a dub_id cookie set by the marketing redirect. The captureDubReferralSignup function handles this initial attribution without blocking the signup flow.

The captureDubReferralSignup Function

Located at lines 61-70 in src/server/referrals/dub.ts, this function reads the Dub cookie and stores the click ID in KV under the key dub:referred-user:<userId> with a TTL of approximately 90 days. It then asynchronously posts a lead event to Dub's POST /track/lead endpoint. The implementation is deliberately fault-tolerant—failures are logged via PostHog but never throw exceptions that could interrupt user registration.

import { captureDubReferralSignup } from "@/server/referrals/dub";

// Simulate a signup with Dub attribution
const fakeRequest = new Request("https://openseo.so", {
  headers: { cookie: "dub_id=abc123" },
});

await captureDubReferralSignup("user_42", fakeRequest);

Step 2: Pinning Referrals to Organizations

User-level referrals must transfer to organizations because billing occurs at the org level. The markDubReferredOrganization function (lines 23-40 in src/server/referrals/dub.ts) executes on each request session to perform this mapping.

The function checks if the user has a referral pin in KV. If found, it looks up the organization the user founded (the first organization they created) and writes a KV entry dub:referred-org:<orgId><userId> with a TTL of approximately 400 days. This long-lived marker enables the billing system to discover referral relationships months after the initial signup.

Step 3: Real-Time Webhook Processing

When Autumn emits a billing.updated webhook, the trackDubSalesForOrganization function (lines 29-34) reads the organization's referral pin and fires a fire-and-forget sweep via sweepDubSalesForOrganization. This path handles the majority of first-time purchases and immediate renewals.

The webhook handler is defined in src/server/billing/autumn-webhook.ts and provides the fastest path to commission attribution. However, it cannot catch delayed invoices, manual top-ups, or webhook delivery failures, which necessitates the cron-based fallback.

Step 4: The Daily Cron Sweep Process

The Dub referral sweep process runs daily via a Cloudflare Workers cron trigger configured in wrangler.jsonc. When executed, the handler calls sweepDubReferredOrganizations to ensure no referred revenue goes unattributed.

sweepDubReferredOrganizations Implementation

This function (lines 56-89 in src/server/referrals/dub.ts) serves as the entry point for the scheduled job. It iterates over all KV entries with the prefix dub:referred-org: using KV.list with pagination support via the cursor parameter. For each discovered organization, it retrieves the associated user ID and invokes sweepDubSalesForOrganization.

The pagination handling ensures the sweep completes even if the platform hosts thousands of referred organizations, processing entries in batches until the list is exhausted.

Per-Organization Sale Processing

The sweepDubSalesForOrganization function (lines 77-90) performs the granular work of invoice inspection and sale reporting:

  1. Invoice Retrieval: Fetches the organization's invoices from Autumn using autumn.customers.get() with expand: ["invoices"]
  2. Window Filtering: Only processes invoices newer than the configurable 45-day sale-sweep window
  3. Deduplication Check: Reads KV for dub:sale:<invoiceId> markers to prevent double-counting
  4. Sale Construction: Builds the request payload via buildDubSaleRequest
  5. API Submission: Calls trackDubSale (lines 42-66) to POST to Dub's /track/sale endpoint
  6. Marker Writing: On success, writes dub:sale:<invoiceId> = "1" to KV; non-referred invoices receive a 1-hour TTL marker for retry logic

Errors during individual invoice processing are logged but do not abort the loop, ensuring one problematic invoice cannot prevent others from being processed.

import { sweepDubReferredOrganizations } from "@/server/referrals/dub";

// Manually invoke the daily sweep for testing or debugging
await sweepDubReferredOrganizations();

Error Handling and Idempotency Mechanisms

The sweep implements multiple safeguards to ensure reliability:

  • Missing API Keys: All entry points early-return if getDubApiKey() returns falsy, preventing errors in development environments
  • Retry Logic: Lead events receive 2 retry attempts; sale events use single attempts with PostHog error capture (captureServerError)
  • Idempotency: KV markers (dub:sale:<invoiceId>) guarantee that identical invoices never generate duplicate Dub sales
  • Non-Referred Handling: When Dub returns customer: null, the system sets a short-lived marker (1-hour TTL) allowing the next sweep to retry after the lead materializes
  • Fault Isolation: Each invoice processes in its own try-catch block; failures affect only the individual record

Summary

  • The Dub referral sweep process runs daily via Cloudflare Workers cron to catch invoice events missed by real-time webhooks
  • captureDubReferralSignup stores click IDs in KV with 90-day TTLs, while markDubReferredOrganization creates 400-day org-level pins
  • The sweep iterates all dub:referred-org: KV entries and processes invoices newer than 45 days via sweepDubSalesForOrganization
  • Idempotency is enforced through dub:sale:<invoiceId> markers, with 1-hour TTLs for pending non-referred invoices
  • All referral logic resides in src/server/referrals/dub.ts, triggered from src/server.ts and scheduled in wrangler.jsonc

Frequently Asked Questions

How does the system prevent duplicate Dub sale events?

The system checks for a KV marker at dub:sale:<invoiceId> before processing any invoice. If the marker exists, the invoice is skipped. After successfully posting to Dub's /track/sale endpoint, the system writes the marker with a permanent value. This ensures that even if the cron sweep runs multiple times or retries occur, each invoice generates exactly one sale event.

What happens to the sweep if the Dub API is temporarily unavailable?

Errors during the trackDubSale call are caught and logged to PostHog via captureServerError, but the loop continues processing remaining invoices. Non-referred invoices (where Dub returns customer: null) receive a 1-hour TTL marker instead of a permanent one, allowing the sweep to retry them during the next execution once the lead data propagates through Dub's systems.

Why does the system use both webhooks and a daily cron sweep?

The webhook path (billing.updated events from Autumn) provides immediate attribution for first-time purchases and standard renewals that occur while the system is active. However, webhooks can fail to deliver, be delayed, or miss top-up purchases and manual billing adjustments. The daily cron sweep acts as a reconciliation mechanism, scanning the previous 45 days of invoices to ensure no referred revenue escapes attribution regardless of webhook reliability.

Where is the cron schedule configured, and can it be invoked manually?

The schedule is defined in wrangler.jsonc as a Cloudflare Workers cron trigger, typically set to run once per day. While the system runs automatically on this schedule, you can import and invoke sweepDubReferredOrganizations from src/server/referrals/dub.ts manually in test environments or maintenance scripts to force an immediate reconciliation of pending referrals.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →