Skip to main content

Transfer Runbook

Use this runbook when transferring a Factory app to a buyer. Fill in {app} with the app slug (e.g., factory-crm).

Pre-Transfer Checklist

  • Buyer has a GitHub account and Cloudflare account
  • Buyer has a Stripe account (for Stripe account transfer or fresh keys)
  • Export factory_events for this app’s users to a CSV/S3 archive (stays with Factory)
  • Set an export date — all events for this app are archived before transfer
  • Confirm no cross-app code coupling (no other app imports {app} code)
  • Revoke buyer’s temporary access to Factory infrastructure after transfer

Transfer Steps

1. Archive factory_events data

2. Transfer GitHub repository

After transfer, the buyer’s org becomes the owner. Buyer should immediately update CI secrets.

3. Transfer the Neon database

Option A — Neon project transfer (buyer has a Neon account):
  1. In Neon Dashboard → project → Settings → Transfer Ownership
  2. Enter buyer’s Neon email
  3. Buyer accepts the transfer
Option B — pg_dump/restore (buyer uses any Postgres host):

4. Transfer Cloudflare Worker

Option A — Cloudflare dashboard transfer:
  1. Workers & Pages → → Settings → Transfer
Option B — Buyer deploys fresh Worker:

5. Hand off secrets

Generate a one-time secure note (e.g., 1Password Share, Bitwarden Send) containing:
  • JWT_SECRET (buyer must rotate immediately post-transfer)
  • STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET
  • Neon connection string (if not transferring the project)
  • Any third-party API keys (ANTHROPIC_API_KEY, ELEVENLABS_API_KEY, etc.)
Buyer sets secrets on their Worker:

6. Update CI/CD secrets in buyer’s GitHub repo

Buyer must set:
If buyer wants to continue using @latimer-woods-tech/* packages, they also need:
Alternatively, buyer can fork the packages and publish them under their own scope.

7. Update DNS

Transfer DNS for the app’s domain to the buyer’s registrar or Cloudflare account:

8. Revoke Factory access


Post-Transfer Verification Checklist

  • Buyer confirms Worker responds at their domain
  • Buyer confirms /health returns 200
  • Buyer confirms DB connection works
  • Buyer has rotated JWT_SECRET to their own value
  • Buyer has updated Stripe webhook URL to their Worker endpoint
  • Seller confirms factory_events data for this app is scrubbed or archived
  • Seller confirms no Factory CI workflows reference this app’s secrets
  • DNS propagation confirmed (TTL waited)
  • Old Cloudflare Worker route (under Factory account) deleted or disabled