Bulk API 2.0 is the asynchronous interface for moving large volumes of records in and out of Salesforce. The practical difference from version 1.0 is that you stop managing batches: you upload one CSV of up to 150 MB, and Salesforce splits, queues and retries it.
The daily ceiling is 150 million records processed across a 24 hour rolling period, shared between both versions of the Bulk API. Most teams never approach that. The limits they do hit are the per job size cap, the seven day result retention, and the 200 record transaction boundary that quietly decides how partial failures behave.
Bulk API 2.0 vs Bulk API 1.0
| Bulk API 2.0 | Bulk API (1.0) | |
|---|---|---|
| Who creates batches | Salesforce, automatically | You |
| Max size | 150 MB per job | 10 MB per batch |
| Records per batch | Managed for you | 10,000 |
| Characters per batch | Managed for you | 10,000,000 |
| Query jobs | 10,000 per 24 hour rolling window | 30 query attempts at 5 minute intervals |
| Query results ceiling | 1 TB per 24 hours | 1 GB per retrieved file, 15 files max |
| Retries | Handled by the API | Yours to write |
| Use it when | Almost always | You need explicit control of batch boundaries |
Version 1.0 is not deprecated and still has a narrow use: when you need to decide batch boundaries yourself, usually because records within a batch interact and you want them grouped. Everything else should be on 2.0.
The limits that actually matter
Shared across both versions
- 150,000,000 records processed per 24 hour rolling period for ingest jobs
- 15,000 batches per 24 hour rolling period, shared between the two APIs
That second one surprises people who moved to 2.0 expecting the batch concept to disappear. It disappeared from your code, not from the accounting. Salesforce still creates batches internally and they still count.
Per job and per record
| Limit | Value |
|---|---|
| Max job size, Bulk API 2.0 | 150 MB |
| Recommended upload size | 100 MB |
| Max characters per record | 400,000 |
| Max characters per field | 131,072 |
| Max fields per record | 5,000 |
| Completed job retention | 7 days |
| Max job creation window | 24 hours |
The gap between the 150 MB cap and the 100 MB recommendation is base64 encoding. Data expands in transit, so a file comfortably under the hard limit locally can arrive over it. Size against 100 MB and the question never comes up.
Compression is gzip only, and it does not buy you headroom: compression does not change the character or batch size limits, it only speeds the transfer.
How it counts against your API allocation
Each HTTP request counts as one call for usage limit purposes. That is the whole reason Bulk API exists. Loading a million records through the REST API means a million calls against an allocation that starts at 100,000 plus a per licence multiplier on Enterprise Edition. The same load through Bulk API 2.0 is a handful of requests: create the job, upload the data, close it, poll for status.
For where that allocation number comes from and how to read it, see our guide to Salesforce API rate limits.
The 200 record transaction boundary
Each chunk of 200 records is processed as a separate transaction. This one line explains most confusing Bulk API behaviour.
It means a job is not atomic. A 100,000 record load that fails halfway leaves the first half committed. There is no rollback, and asking for one is asking for something the API does not offer.
It also means Apex triggers on the loaded object fire per chunk, not per job, and governor limits reset at each boundary. A trigger that works fine on 200 records works fine at any job size. A trigger that assumes it sees the whole load at once does not.
Three consequences worth designing around:
- Make loads idempotent. Use an external ID and upsert rather than insert, so a rerun after a partial failure converges instead of duplicating.
- Always read the failed records result. A job status of complete means Salesforce finished processing, not that every record succeeded.
- Pull results within seven days. Completed job results are deleted permanently after that, and there is no recovery.
Querying with Bulk API 2.0
Query jobs get their own allocations: 10,000 query jobs per 24 hour rolling window, and 1 TB of total query results across the same window.
Retries are handled for you, with one caveat worth knowing before it wastes an afternoon. If you receive a message that the API retried more than 15 times, the answer is not to retry harder, it is to add filter criteria. That message means the query is too broad to complete, and the fix is a narrower query rather than more patience.
When not to use Bulk API
Bulk API is asynchronous, which is a feature for a nightly load and a problem for anything a person is waiting on.
| Volume and context | Use |
|---|---|
| A handful of records, user is waiting | REST API, single requests |
| Up to a few thousand, user is waiting | Composite or sObject Collections |
| Tens of thousands or more, no one waiting | Bulk API 2.0 |
| Continuous change, external system mirroring Salesforce | Change Data Capture, not a periodic bulk pull |
That last row is the one worth pausing on. Teams often build a nightly bulk export to keep an external store current, then spend months tuning it. If the requirement is a mirror that stays in step, an event stream is the better shape, and our comparison of platform events and Change Data Capture covers the trade-offs.
Frequently Asked Questions
What is the difference between Bulk API and Bulk API 2.0?
Bulk API 2.0 manages batching for you: you upload a single file of up to 150 MB and Salesforce splits, queues and retries it. Bulk API 1.0 requires you to create batches yourself, capped at 10 MB and 10,000 records each. Both share the same daily allocation of 150 million records and 15,000 batches.
What is the Bulk API 2.0 limit?
150 MB per job, with 100 MB recommended to allow for base64 expansion in transit. Across a 24 hour rolling period, both API versions share 150,000,000 records processed and 15,000 batches. Query jobs are capped at 10,000 per 24 hours with 1 TB of total results.
Does Bulk API count against Salesforce API limits?
Yes, but efficiently. Each HTTP request counts as one call, and a Bulk API job is only a few requests regardless of how many records it carries. That is the point of using it: the same volume through the REST API would be one call per record.
How long are Bulk API results available?
Seven days. Job status and batch result sets for completed jobs are available for seven days, after which the data is deleted permanently. Anything you need from a job, including the failed record list, has to be pulled inside that window.
Is a Bulk API job atomic?
No. Each chunk of 200 records is processed as a separate transaction, so a job that fails partway leaves earlier chunks committed. Use an external ID with upsert so that reruns converge rather than duplicate.
Why does my Bulk API query keep retrying?
The API handles retries automatically, but a message saying it retried more than 15 times means the query is too broad to complete within its processing window. Add filter criteria to narrow it rather than retrying again.
Can I compress Bulk API uploads?
Yes, with gzip, which is the only accepted compression. It speeds transfer but does not affect the character or batch size limits, so it does not give you extra headroom against the caps.
Related Articles
- Salesforce API rate limits and native integration advantages
- Platform events vs Change Data Capture
- Salesforce integration patterns and best practices
- Governor limits in verified managed packages
Sources
- Salesforce Developers, Bulk API and Bulk API 2.0 Limits and Allocations: daily records, batch allocation, job and record size caps, query job limits. 2/ Salesforce Developers, Bulk API 2.0 and Bulk API Developer Guide: 200 record transaction chunks, one call per HTTP request, gzip compression, seven day retention. 3/ Salesforce Developers, API Request Limits and Allocations. Verified 2 September 2026.



