Skip to content

Instantly share code, notes, and snippets.

@weytani
Last active March 17, 2026 23:32
Show Gist options
  • Select an option

  • Save weytani/907a0d631fefbe49e769c87b5bb3a676 to your computer and use it in GitHub Desktop.

Select an option

Save weytani/907a0d631fefbe49e769c87b5bb3a676 to your computer and use it in GitHub Desktop.
SFDMU Test Data Quickstart — seed Accounts, Contacts, Cases, Contracts & Products into lower Salesforce environments

SFDMU Test Data Quickstart

Seed Accounts, Contacts, Cases, Contracts, and Products into lower Salesforce environments using SFDMU (Salesforce Data Move Utility).


How It Works

SFDMU uses a single export.json config file to define which objects and fields to migrate. You can pull from a source org or from local CSV files. Objects are processed in dependency order automatically — parent records (Account) before children (Contact, Case, etc.).

your-sfdmu-project/
├── export.json        # Migration config
├── Account.csv        # Optional: seed data from CSV instead of org
├── Contact.csv
├── Case.csv
├── Contract.csv
└── Product2.csv

CLI Commands

# Org-to-org (pull from source, push to target)
sf sfdmu run -s [email protected] -u [email protected]

# CSV-to-org (seed from local CSV files)
sf sfdmu run -s csvfile -u [email protected]

# Dry run (no changes made)
sf sfdmu run -s csvfile -u [email protected] --simulation

# Skip interactive prompts (CI/CD)
sf sfdmu run -s csvfile -u [email protected] --noprompt

Exporting Data from Production

Use SFDMU to pull a controlled slice of prod data into local CSV files, then use those CSVs to seed sandboxes. This gives you a versioned, repeatable dataset you can check into source control.

Step 1: Export prod to CSV

Set --targetusername csvfile to write query results to local CSV files instead of another org.

sf sfdmu run -s [email protected] -u csvfile -p ./sfdmu-data

This runs every query in your export.json against prod and writes the results as CSV files alongside it (Account.csv, Contact.csv, etc.).

Step 2: Scope your queries

Keep prod exports small and intentional. Use WHERE clauses and LIMIT to avoid pulling the entire org.

{
  "query": "SELECT Name, Industry, Phone FROM Account WHERE CreatedDate = LAST_N_DAYS:90 LIMIT 50",
  "operation": "Upsert",
  "externalId": "Name"
}

Step 3: Anonymize if needed

If the export contains PII, add updateWithMockData and mockFields (see Data Anonymization below) so sensitive values are replaced with fake data during the export.

Step 4: Seed a sandbox from the exported CSVs

sf sfdmu run -s csvfile -u [email protected] -p ./sfdmu-data

Typical workflow

Production ──(export to CSV)──► Local CSVs ──(commit to repo)──► Seed any sandbox
                                    │
                                    └── anonymize PII before committing

Heads up: Use --canmodify (-c) if your source is a production org and SFDMU prompts for confirmation. The --simulation flag is your friend for the first run.


The Template

This export.json seeds five core objects with their required fields. Each object uses Upsert with a natural key so you can re-run safely without creating duplicates.

{
  "$schema": "https://raw.githubusercontent.com/forcedotcom/SFDX-Data-Move-Utility/main/schemas/export.schema.json",
  "excludeIdsFromCSVFiles": true,
  "objects": [
    {
      "query": "SELECT Name, Industry, Phone, BillingStreet, BillingCity, BillingState, BillingPostalCode, BillingCountry FROM Account WHERE Name LIKE 'Test%' LIMIT 50",
      "operation": "Upsert",
      "externalId": "Name"
    },
    {
      "query": "SELECT FirstName, LastName, Email, Phone, AccountId, Title, MailingCity, MailingState FROM Contact WHERE Account.Name LIKE 'Test%' LIMIT 100",
      "operation": "Upsert",
      "externalId": "Email"
    },
    {
      "query": "SELECT Subject, Status, Priority, Origin, ContactId, AccountId, Description FROM Case WHERE Account.Name LIKE 'Test%' LIMIT 100",
      "operation": "Upsert",
      "externalId": "Subject",
      "master": false
    },
    {
      "query": "SELECT ContractNumber, AccountId, Status, StartDate, ContractTerm FROM Contract WHERE Account.Name LIKE 'Test%' LIMIT 50",
      "operation": "Upsert",
      "externalId": "ContractNumber",
      "master": false
    },
    {
      "query": "SELECT Name, ProductCode, Family, IsActive, Description FROM Product2 WHERE IsActive = true LIMIT 50",
      "operation": "Upsert",
      "externalId": "ProductCode"
    }
  ]
}

Object Breakdown

Account

The root parent — most other objects look up to it. Name works as a natural external ID for test data.

Field Why
Name Required. Also our upsert key.
Industry, Phone Common fields for realistic test data.
Billing* Address fields — useful for geo-dependent logic.

Contact

Child of Account via AccountId. SFDMU resolves the Account relationship automatically as long as Account is in the same migration.

Field Why
FirstName, LastName Required (LastName is mandatory).
Email Our upsert key — must be unique per contact.
AccountId Links to parent Account. SFDMU handles the lookup.

Case

Child of both Account and Contact. master: false means only Cases linked to the migrated Accounts/Contacts are transferred.

Field Why
Subject Our upsert key — keep unique per case.
Status, Priority, Origin Required by default Case page layout / validation.
ContactId, AccountId Relationships resolved from earlier objects.

Contract

Child of Account. ContractNumber is auto-generated on insert but serves as our upsert key for re-runs.

Field Why
ContractNumber Auto-number field, used as upsert key.
AccountId Required parent lookup.
Status, StartDate, ContractTerm Required fields for a valid Contract.

Product2

Standalone — no parent dependency. Products are org-wide, not account-specific.

Field Why
Name Required.
ProductCode Our upsert key — must be unique per product.
Family, IsActive Common classification fields.

CSV Seed Files

When using --sourceusername csvfile, place CSV files in the same directory as export.json. Column headers must match API field names. Use relationship notation for lookups.

Account.csv

Name,Industry,Phone,BillingCity,BillingState,BillingCountry
Test Acme Corp,Technology,415-555-0100,San Francisco,CA,US
Test Globex Inc,Manufacturing,312-555-0200,Chicago,IL,US
Test Initech LLC,Finance,212-555-0300,New York,NY,US

Contact.csv — use Account.Name to reference the parent:

FirstName,LastName,Email,Phone,Account.Name,Title
Jane,Doe,[email protected],415-555-0101,Test Acme Corp,VP Engineering
John,Smith,[email protected],312-555-0201,Test Globex Inc,Director of Ops
Alice,Park,[email protected],212-555-0301,Test Initech LLC,CFO

Case.csv

Subject,Status,Priority,Origin,Account.Name,Contact.Email,Description
Test Billing Issue,New,High,Email,Test Acme Corp,[email protected],Monthly invoice discrepancy
Test Feature Request,New,Medium,Web,Test Globex Inc,[email protected],Request for API access
Test Login Problem,New,High,Phone,Test Initech LLC,[email protected],SSO not redirecting

Contract.csv

ContractNumber,Account.Name,Status,StartDate,ContractTerm
CON-0001,Test Acme Corp,Draft,2025-01-01,12
CON-0002,Test Globex Inc,Draft,2025-06-01,24
CON-0003,Test Initech LLC,Draft,2025-03-15,6

Product2.csv

Name,ProductCode,Family,IsActive,Description
Test Widget Pro,WIDGET-PRO,Hardware,true,Standard widget unit
Test Cloud Suite,CLOUD-SUITE,Software,true,SaaS platform license
Test Support Plan,SUPPORT-PLAN,Services,true,24/7 premium support

Data Anonymization

When pulling from a production org, anonymize PII before landing it in sandboxes. Add mockFields and set updateWithMockData: true on the object.

{
  "query": "SELECT FirstName, LastName, Email, Phone, AccountId FROM Contact",
  "operation": "Upsert",
  "externalId": "Email",
  "updateWithMockData": true,
  "mockFields": [
    { "name": "FirstName", "pattern": "first_name" },
    { "name": "LastName", "pattern": "last_name" },
    { "name": "Email", "pattern": "email" },
    { "name": "Phone", "pattern": "phone" }
  ]
}

Common Mock Patterns

Pattern Output Example Use For
first_name "Maria" First names
last_name "Johnson" Last names
name / full_name "Alex Turner" Full names
email "[email protected]" Email addresses
phone "+1-555-0142" Phone numbers
city "Portland" City names
street "742 Evergreen Ter" Street addresses
zip "97201" Postal codes
country "United States" Country names
company_name "Acme Corp" Company/Account names
sentence "Lorem ipsum..." Description fields
url "https://example.com" Website fields
integer 42 Numeric fields

Special Functions

c_seq_number('ACCT-', 1000, 1)     → "ACCT-1000", "ACCT-1001", "ACCT-1002"
c_seq_date('2025-01-01', 'd')      → "2025-01-01", "2025-01-02", "2025-01-03"
c_set_value('Test Account')        → Sets every record to "Test Account"

Anonymize All Fields (with exceptions)

{
  "updateWithMockData": true,
  "mockFields": [
    {
      "name": "all",
      "pattern": "sentence",
      "excludeNames": ["Email", "AccountId", "Status"]
    }
  ]
}

Other Useful Features

Feature What It Does Docs
deleteOldData Wipe target records before inserting — clean slate per run ScriptObject
simulationMode Dry run the entire migration without touching the target Script Object
useValuesMapping Transform field values during migration via ValueMapping.csv Record Transformation
fieldMapping Map source field names to different target field names ScriptObject
sourceRecordsFilter Filter source records after query (SQL-like expressions) ScriptObject
objectSets Split migration into sequential phases for complex dependencies Export.json Overview
LIMIT in queries Control volume — start small, scale up Built into SOQL
allOrNone Fail the entire batch if any record errors — strict mode Script Object
excludedFields Drop specific fields from migration without editing the query ScriptObject
Add-ons Run custom JS before/after migration for transforms, validation Advanced Examples

Tips

  • Order doesn't matter in the objects array — SFDMU resolves dependency order automatically.
  • master: false on child objects ensures only records related to migrated parents are transferred. Without it, the query runs unrestricted.
  • excludeIdsFromCSVFiles: true at root level prevents Salesforce IDs in CSVs from being treated as real IDs in the target org.
  • Re-run safely: Upsert with a natural key means running the migration twice won't create duplicates.
  • Start with --simulation to validate your config before writing to the target.
  • Relationship notation: In CSV files, use Account.Name (not AccountId) to reference parent records by their external ID.

Sources: SFDMU Help Center · Basic Examples · Data Anonymization · ScriptObject Reference · CSV Examples

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment