Relevant source files
The following files were used as context for generating this wiki page:
Overview
The POST -> CreateNamespace flow handles the full, permanent deletion lifecycle of a partner from a program within Dub. It coordinates database record cleanup, cascades deletion to associated links, dispatches search synchronization jobs to keep index state consistent, and initializes the Turbopuffer search provider namespace when communicating with vector and full-text search backends.
Sources: apps/web/app/(ee)/api/cron/partners/delete/route.ts:19-23, apps/web/lib/api/partners/search/providers/turbopuffer.ts:123-136
Step-by-Step Execution Flow
Step 1: Handle Partner Deletion Request (POST)
The execution begins at the cron API route endpoint POST inside apps/web/app/(ee)/api/cron/partners/delete/route.ts. Wrapped with withCron, the handler parses the request body using a Zod schema (inputSchema) to extract workspaceId, programId, partnerId, and userId. It checks if the partner enrollment exists and validates that the partner is eligible for permanent deletion by inspecting associated link statistics, active commissions, and payouts. If valid, it purges dependent records (such as submitted leads, fraud events, messages, and discovered partners), invokes bulk link deletion, deletes the program enrollment, and updates workspace partner usage quotas.
Sources: apps/web/app/(ee)/api/cron/partners/delete/route.ts:20-160
Step 2: Bulk Delete Links (bulkDeleteLinks)
When a partner enrollment contains active short links (links.length > 0), the route invokes bulkDeleteLinks in apps/web/lib/api/links/bulk-delete-links.ts. This function processes links in batches of 100 (DELETE_LINKS_BATCH_SIZE). For each batch, it identifies and deletes associated discount codes, removes link records in a Prisma transaction while decrementing project total links counters, and asynchronously cleans up external caches (Redis linkCache, Tinybird analytics, R2 storage assets, and partner search index synchronization queues).
Sources: apps/web/lib/api/links/bulk-delete-links.ts:23-78
Step 3: Queue Partner Search Sync for Links (queuePartnerSearchSyncForLinks)
Inside the asynchronous cleanups of bulkDeleteLinks, if any deleted links were associated with a partner (link.partnerId), queuePartnerSearchSyncForLinks is invoked. It maps the deleted links by their programId and partnerId pairs to ensure updates are grouped by program rather than flooded per link, preparing payloads for synchronization.
Sources: apps/web/lib/api/partners/queue-partner-search-sync.ts:100-125
Step 4: Queue Partner Search Sync (queuePartnerSearchSync)
Both the link-level sync queue and the main cron route (after deleting the program enrollment itself) call queuePartnerSearchSync. This function verifies whether a partner search provider is active. If configured, it divides enrollment and partner IDs into batches and dispatches them to partnerSearchSyncJob with a default delay (PARTNER_SEARCH_SYNC_DELAY_SECONDS of 5 seconds) to ensure database mutations have fully committed before background workers query them back.
Sources: apps/web/lib/api/partners/queue-partner-search-sync.ts:44-83
Step 5: Get Partner Search Provider (getPartnerSearchProvider)
When search operations or background sync jobs need to communicate with the vector and search backend, they invoke getPartnerSearchProvider in apps/web/lib/api/partners/search/provider.ts. This function checks for the presence of TURBOPUFFER_API_KEY. If present, it caches and returns an instance of the Turbopuffer search provider, avoiding repeated TLS handshake and connection pool setup costs across invocations.
Sources: apps/web/lib/api/partners/search/provider.ts:12-20
Step 6: Create Turbopuffer Partner Search Provider (createTurbopufferPartnerSearchProvider)
Invoked by the provider factory, createTurbopufferPartnerSearchProvider constructs the search client interface. It sets up methods for candidate searching (searchCandidates), counting (countCandidates), bulk upserts (upsert), and document deletions (delete). Each write operation automatically chunks payloads (WRITE_BATCH_SIZE of 500) and wraps requests in transient retry logic.
Sources: apps/web/lib/api/partners/search/providers/turbopuffer.ts:345-421
Step 7: Create Namespace (createNamespace)
Underpinning the search provider operations, createNamespace initializes a connection to the Turbopuffer SDK using the API key and configured region (aws-us-east-1). It binds to the canonical multi-tenant namespace (defined as partner-search-v4) which aggregates all program documents while maintaining strict filter-level isolation via programId.
Sources: [apps/web/lib/api/partners/search/providers/turbopuffer.ts:34-34, 123-136](https://github.com/blade47/dub/blob/7c93d97abf0ecd37fb669c6a68a1f7ef9109daea/apps/web/lib/api/partners/search/providers/turbopuffer.ts#L34-L34, L123-L136)
Sequence Diagram
Sources: apps/web/app/(ee)/api/cron/partners/delete/route.ts:131-163, apps/web/lib/api/links/bulk-delete-links.ts:47-73, apps/web/lib/api/partners/queue-partner-search-sync.ts:44-124, apps/web/lib/api/partners/search/provider.ts:12-20, [apps/web/lib/api/partners/search/providers/turbopuffer.ts:123-136, 345-352](https://github.com/blade47/dub/blob/7c93d97abf0ecd37fb669c6a68a1f7ef9109daea/apps/web/lib/api/partners/search/providers/turbopuffer.ts#L123-L136, L345-L352)
Flowchart
Sources: apps/web/app/(ee)/api/cron/partners/delete/route.ts:20-183, apps/web/lib/api/links/bulk-delete-links.ts:23-78, apps/web/lib/api/partners/queue-partner-search-sync.ts:44-83, apps/web/lib/api/partners/search/provider.ts:12-20, [apps/web/lib/api/partners/search/providers/turbopuffer.ts:123-136, 345-352](https://github.com/blade47/dub/blob/7c93d97abf0ecd37fb669c6a68a1f7ef9109daea/apps/web/lib/api/partners/search/providers/turbopuffer.ts#L123-L136, L345-L352)
Key Observations
Important
Resilience and Non-Blocking Queueing: The search sync queueing mechanism (queuePartnerSearchSync) is designed to never throw errors that would fail the core partner deletion mutation. If QStash publishing fails, it falls back to the outbox pattern.
Note
Connection Caching: The Turbopuffer search provider instance is cached per process (cachedSearchProvider), ensuring that high-frequency background jobs and searches reuse established HTTP connection pools and avoid redundant TLS handshakes.
Sources: apps/web/lib/api/partners/queue-partner-search-sync.ts:40-43, apps/web/lib/api/partners/search/provider.ts:5-20
On This Page
OverviewStep-by-Step Execution FlowStep 1: Handle Partner Deletion Request (POST)Step 2: Bulk Delete Links (bulkDeleteLinks)Step 3: Queue Partner Search Sync for Links (queuePartnerSearchSyncForLinks)Step 4: Queue Partner Search Sync (queuePartnerSearchSync)Step 5: Get Partner Search Provider (getPartnerSearchProvider)Step 6: Create Turbopuffer Partner Search Provider (createTurbopufferPartnerSearchProvider)Step 7: Create Namespace (createNamespace)Sequence DiagramFlowchartKey Observations