Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Sf Data Management

ASecurity

Moving records in and out of a Salesforce org - choosing between sObject tree seeding, Bulk API 2.0 and synchronous composite calls by volume, the sf data command surface (import bulk, export bulk, upsert bulk, delete bulk, import tree, export tree, query, resume), external ids and upsert keys, load ordering for parent-child data, Bulk API 2.0 limits and allocations, hard delete and the Recycle Bin, CSV shaping and field caps, scratch org and sandbox seeding, and data-loss safety on destructi...

2 stars
0 votes
0 copies
0 views
Added 9/19/2026
developmentgoshellbashnodeapisecurity

Works with

terminalcliapi

Security Analysis

A100/100

Scanned 9/19/2026

Install to Claude Code

$npx -y skills add grzmol/vibe-force --skill sf-data-management --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Sf Data Management?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Sf Data Management
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/grzmol-sf-data-management/badge)](https://www.skillsdirectory.com/skills/grzmol-sf-data-management)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: sf-data-management
description: Moving records in and out of a Salesforce org - choosing between sObject tree seeding, Bulk API 2.0 and synchronous composite calls by volume, the sf data command surface (import bulk, export bulk, upsert bulk, delete bulk, import tree, export tree, query, resume), external ids and upsert keys, load ordering for parent-child data, Bulk API 2.0 limits and allocations, hard delete and the Recycle Bin, CSV shaping and field caps, scratch org and sandbox seeding, and data-loss safety on destructive schema changes. Use when seeding a scratch org, migrating or backfilling records, writing a data load script, extracting production-shaped test data, or planning a schema change that moves or drops data.
---

# Data Management

## When to use

- Seeding a scratch org or a developer sandbox so the feature under test has records to work on.
- Backfilling a new field, migrating records between orgs, or extracting a sample of real data.
- Planning a schema change that moves, reshapes or drops data.
- A deploy is blocked because a field cannot be deleted while data still references it.

This skill covers moving **records**. Moving **metadata** is skill `sf-deployment-strategies`;
`sfdx-project.json` and package directories are skill `sf-project-structure`.

## Pick the mechanism by volume

| Records | Mechanism | Command |
| --- | --- | --- |
| A handful, hand-written, relationships by reference | sObject tree | `sf data import tree` |
| 1 to a few hundred, ad hoc | Single-record commands | `sf data create record`, `sf data update record`, `sf data delete record` |
| Under 2,000 | Bulkified synchronous REST (Composite) or SOAP | Outside the CLI, or `sf data import bulk` anyway |
| Over 2,000 | **Bulk API 2.0** | `sf data import bulk`, `sf data upsert bulk`, `sf data update bulk`, `sf data delete bulk` |
| Reading over 10,000 | **Bulk API 2.0 query** | `sf data export bulk` |
| Reading under 10,000 | Synchronous query | `sf data query` |

The 2,000 threshold is the guide's own: "Any data operation that includes more than 2,000 records
is a good candidate for Bulk API 2.0. Jobs with fewer than 2,000 records should involve bulkified
synchronous calls in REST (for example, Composite) or SOAP."

The 10,000 threshold is the CLI's own advice: if `sf data query` would return more than 10,000
records, use `sf data export bulk` instead.

## Core patterns

### 1. Seed a scratch org from a tree plan

Export a shaped sample once, commit it, replay it forever:

```bash
sf data export tree \
  --query "SELECT Id, Name, Industry, (SELECT FirstName, LastName, Email FROM Contacts) FROM Account WHERE Industry != null LIMIT 20" \
  --plan --prefix seed --output-dir data/seed \
  --target-org acme-uat
```

`--plan` writes one JSON file per sObject plus a plan definition file. Import it into a fresh org:

```bash
sf data import tree --plan data/seed/seed-Account-Contact-plan.json --target-org my-scratch
```

Two facts that decide whether you use `--plan` or `--files`:

- Files listed in a **plan** may contain **more than 200 records**; the CLI batches them to respect
  the API's 200-record limit. Files passed with `--files` may not.
- **Order matters.** A file whose records have lookups into another file must be listed *after* it.
  Accounts before Contacts.

Plan schema: `items` (one entry per sObject type), each with `sobject` (the type name; child file
references must have roots of this type) and `files` (an array of file paths, in load order).

### 2. Load volume with Bulk API 2.0

```bash
sf data import bulk \
  --file data/accounts.csv \
  --sobject Account \
  --wait 10 \
  --target-org acme-uat
```

Without `--wait` the command starts the job, prints the id and hands the terminal back. Resume with:

```bash
sf data import resume --use-most-recent --wait 10 --target-org acme-uat
sf data bulk results --job-id <id> --target-org acme-uat
```

`--wait 0` is the default. In a script, either wait or record the job id - a fire-and-forget load
that nobody checks is a load that silently half-failed.

### 3. Upsert on an external id, never on a guessed match

```bash
sf data upsert bulk \
  --file data/accounts.csv \
  --sobject Account \
  --external-id Legacy_Id__c \
  --wait 10 \
  --target-org acme-uat
```

`--external-id` is **required** and accepts either a custom external id field or `Id`. An upsert
inserts when the key does not match and updates when it does. That is the only safe way to make a
load re-runnable.

Design the external id field with **External ID** and **Unique** set. Without unique, a duplicate
key makes the upsert ambiguous and the row fails.

### 4. Relate records without knowing Ids

In an sObject tree file, `referenceId` names a record and `@ref` points at it:

```json
{
  "records": [
    {
      "attributes": { "type": "Account", "referenceId": "acme" },
      "Name": "Acme",
      "Industry": "Manufacturing"
    },
    {
      "attributes": { "type": "Contact", "referenceId": "ada" },
      "LastName": "Lovelace",
      "AccountId": "@acme"
    }
  ]
}
```

In a CSV load, the equivalent is a relationship column keyed on the parent's external id:

```csv
LastName,Account.Legacy_Id__c
Lovelace,LEG-1001
```

That avoids a two-pass load entirely: no query for parent ids between the two files.

### 5. Extract volume out

```bash
sf data export bulk \
  --query "SELECT Id, Name, Account.Name FROM Contact" \
  --output-file out/contacts.csv \
  --result-format csv \
  --wait 10 \
  --target-org acme-uat
```

`--all-rows` includes soft-deleted records. `--query-file` reads the SOQL from a file, which keeps a
long query out of shell quoting. Resume a timed-out export with `sf data export resume`.

### 6. Delete, and decide about the Recycle Bin

```bash
sf data delete bulk --sobject Account --file data/delete.csv --wait 10 --target-org acme-uat
```

The CSV must have **one column, `Id`**, and one record id per line.

`--hard-delete` marks the records immediately eligible for deletion instead of sending them to the
Recycle Bin. Hard delete is not reversible. The vibe-force Bash guard blocks destructive data
operations against a production alias unless `VF_ALLOW_PROD=1` is set - that guard exists because
this flag exists.

### 7. Query in a script

```bash
sf data query \
  --query "SELECT COUNT(Id) total FROM Account WHERE Legacy_Id__c != null" \
  --target-org acme-uat --json | jq '.result.records[0].total'
```

`--result-format` takes `human` (default), `csv` or `json`; `--json` overrides it. `--use-tooling-api`
switches to Tooling objects. Post-deploy verification queries live in skill
`sf-post-deploy-verification`.

## Limits that shape the plan

| Item | Bulk API 2.0 |
| --- | --- |
| Batch allocation | 15,000 batches per rolling 24 hours, **shared** with Bulk API 1.0. Only ingest jobs consume batches; query jobs do not |
| Records uploaded per 24 hours | 150,000,000 |
| Maximum file size per job | 150 MB of base64-encoded content. Upload data stays under **100 MB** to leave room for the roughly 50% base64 increase |
| Maximum characters in a field | 131,072 |
| Maximum fields in a record | 5,000 |
| Maximum characters in a record | 400,000 |
| Job lifespan | Terminal-state jobs older than 7 days are deleted; non-terminal jobs are periodically cleaned up |
| Maximum time a job can stay open | 24 hours (ingest jobs only) |
| Results lifespan | Retrievable within 7 days of job completion unless the job is deleted |
| Retries | Handled automatically. "Retried more than 20 times" on ingest means use a smaller file; "more than 15 times" on query means add filter criteria |
| Query results timeout | 20 minutes |

Batches are created for you in Bulk API 2.0. In Bulk API 1.0 you create them yourself, at up to
10,000 records and 10 MB each - which is why 1.0 is the one that runs out of the shared 15,000-batch
allocation first.

Full tables including Bulk API 1.0 and query-job specifics:
[references/bulk-api-limits.md](references/bulk-api-limits.md).

## Data-loss safety

No destructive metadata change without a backout path. The rules that matter:

| Change | Risk | Required handling |
| --- | --- | --- |
| Deleting a field | Data in it is gone | Stop writing it in one release, delete it in a later one. Export the column first |
| Changing a field type | Silent truncation or conversion failure | Export, change, re-import, verify counts |
| Converting a master-detail relationship | **Cannot be converted once data exists** | Rebuild the relationship as a controlled migration |
| Changing an org-wide default to more restrictive | Records disappear from users' views | Verify with a query as an affected user before and after |
| Hard delete | Not reversible | `--hard-delete` never runs against production without `VF_ALLOW_PROD=1` |

Always take a count before and after:

```bash
sf data query --query "SELECT COUNT(Id) c FROM Account" --target-org acme-uat --json | jq '.result.records[0].c'
```

A load that reports success and changes no counts did not do what you think.

## Anti-patterns

### Loading with `Id` as the upsert key from another org

Record ids are not portable between orgs. An upsert on `Id` against a target org where those ids do
not exist inserts duplicates. Use a real external id field.

### A CSV with no external id at all

The load works once. The re-run creates a second copy of everything. Every repeatable load needs a
unique, indexed external id.

### Children before parents

```bash
sf data import tree --files Contact.json,Account.json   # wrong order
```

The Contact lookups have nothing to resolve against. List Accounts first, or use a plan file with
the items in dependency order.

### `sf data query` for a migration extract

Over 10,000 records it is the wrong tool; the CLI says so itself. Use `sf data export bulk`.

### Fire-and-forget bulk jobs in CI

```bash
sf data import bulk --file big.csv --sobject Account --target-org acme-uat
echo "loaded"    # nothing was verified; --wait defaults to 0
```

Either `--wait` and check the exit code, or capture the job id and poll `sf data bulk results`.

### Using Apex to load volume

A migration inside Apex spends the 10,000-DML-row per-transaction limit and the CPU budget for
nothing. Bulk API 2.0 exists so the load happens outside a transaction. See skill
`sf-governor-limits`.

### Seeding with production data unfiltered

Real records carry real personal data. Extract a shaped sample with a `LIMIT` and a `WHERE`, scrub
the columns that matter, and commit *that*. Record-level access rules for the data once loaded are
in skill `sf-security-model`.

## Verification

```bash
# The load itself
sf data import bulk --file data/accounts.csv --sobject Account --wait 10 --target-org <alias>
sf data bulk results --job-id <id> --target-org <alias>

# Counts before and after
sf data query --query "SELECT COUNT(Id) c FROM Account" --target-org <alias> --json | jq '.result.records[0].c'

# Rows that failed to match their parent
sf data query --query "SELECT COUNT(Id) c FROM Contact WHERE AccountId = null" --target-org <alias> --json

# Org storage and API capacity before a big job
sf org list limits --target-org <alias>

# The vibe-force post-deploy gate, which runs verification queries
node "${CLAUDE_PLUGIN_ROOT}/scripts/checks/vf-check.mjs" smoke --target-org <alias>
```

## References

- [references/bulk-api-limits.md](references/bulk-api-limits.md) - Bulk API 2.0 and 1.0 limits and allocations
- [references/cli-data-commands.md](references/cli-data-commands.md) - every `sf data` command with its required flags
- [references/load-recipes.md](references/load-recipes.md) - seeding, migration, backfill and extract recipes end to end

Sibling skills: `sf-cli-operations` (auth, config, JSON output conventions),
`sf-scratch-orgs-sandboxes` (org lifecycle and what seeding runs against),
`sf-project-structure` (`sfdx-project.json`, where seed data lives in the repo),
`sf-soql-sosl-optimization` (selective queries for extracts),
`sf-governor-limits` (why volume does not belong in Apex),
`sf-deployment-strategies` (destructive metadata changes and backout),
`sf-security-model` (access to the data once it is loaded),
`sf-post-deploy-verification` (verification queries after a release).

Sources: Salesforce Developer Limits and Allocations Quick Reference, "Bulk API and Bulk API 2.0
Limits and Allocations"; Bulk API 2.0 and Bulk API Developer Guide; Salesforce CLI command
reference for `sf data`. All Summer '26 / API version 67.0.

Attribution

grzmolgrzmol
View sourceMore from grzmol →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

281612 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2132 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →