CSVBox Performance & Scalability
Measured timings for every stage of an import — file parse, validation, transformation, and destination upload — across files from 100,000 to 2 million rows.
Benchmarks last run: 24 August 2026
Test setup
One sheet, one schema, one machine — deliberately unexceptional hardware, so these read as a realistic floor rather than a best case. Every run below uses the same configuration, so the only variable is the file.
Timings exclude idle time. Each figure is the importer’s own wall-clock timing for that stage, and the end-to-end total is the sum of the four stages — no time spent waiting on the user is counted. The upload stage is measured against a configured destination, which makes it the figure most sensitive to your own systems and connection.
Reproducing the run — sheet configuration & data transform function
The sheet was configured with three columns typed Number, Email and Date, and a single data-transform function applied to col2. The transform is intentionally trivial — one string coercion and an uppercase — so the transformation timings above measure the pipeline’s per-row dispatch overhead, not the cost of your own logic.
- Columns
- 3 of 12 mapped
- col1
- Number
- col2
- col3
- Date
- Validation
- Column type rules
- Transform
- 1 function, on col2
- Virtual columns
- None
- File format
- CSV, UTF-8
const helper = (value) => {
return String(value).toUpperCase();
};
csvbox.row["col2"] = helper(csvbox.row["col2"]);
return csvbox;Source CSVs carry 12 columns — Index, Customer Id, First Name, Last Name, Company, City, Country, Phone 1, Phone 2, Email, Subscription Date, Website — of which 3 were mapped into the sheet. The rest are read by the parser and dropped at mapping, which is why the payload sent is a fraction of the file on disk.
How an import runs
Every import runs the same four stages in order, from the file you hand the importer to the destination it writes to. The numbered sections after this one measure each of them across all four file sizes.
File parse
Reading the CSV off disk and decoding it into rows. The parser sees the whole source file — all 12 columns — before mapping narrows it to the three configured ones, so cost here tracks file size rather than sheet shape.
| Rows | Source file | Payload sent | Duration | Per row | Throughput |
|---|---|---|---|---|---|
| 100k | 17.32 MB | 5.40 MB | 406 ms | 4.06 µs | 246.3k rows/sec |
| 500k | 87.03 MB | 27.85 MB | 1.4s | 2.79 µs | 357.9k rows/sec |
| 1M | 174.16 MB | 55.90 MB | 3.2s | 3.19 µs | 313.1k rows/sec |
| 2M | 349.42 MB | 113.92 MB | 5.6s | 2.78 µs | 359.3k rows/sec |
Validation
Column type rules applied to every cell — Number, Email, and Date across the three mapped columns. Runs in chunks as rows stream in. This is the one stage whose per-row cost climbs with file size rather than holding flat.
| Rows | Source file | Payload sent | Duration | Per row | Throughput |
|---|---|---|---|---|---|
| 100k | 17.32 MB | 5.40 MB | 583 ms | 5.83 µs | 171.5k rows/sec |
| 500k | 87.03 MB | 27.85 MB | 7.3s | 14.55 µs | 68.7k rows/sec |
| 1M | 174.16 MB | 55.90 MB | 17.7s | 17.73 µs | 56.4k rows/sec |
| 2M | 349.42 MB | 113.92 MB | 38.1s | 19.04 µs | 52.5k rows/sec |
Transformation
The sheet’s data-transform function, run once per row. Here it is deliberately trivial — one string coercion and an uppercase on col2 — so these figures measure the pipeline’s per-row dispatch overhead, not the cost of your own logic.
| Rows | Source file | Payload sent | Duration | Per row | Throughput |
|---|---|---|---|---|---|
| 100k | 17.32 MB | 5.40 MB | 188 ms | 1.88 µs | 531.9k rows/sec |
| 500k | 87.03 MB | 27.85 MB | 873 ms | 1.75 µs | 572.7k rows/sec |
| 1M | 174.16 MB | 55.90 MB | 1.6s | 1.59 µs | 627.0k rows/sec |
| 2M | 349.42 MB | 113.92 MB | 6.1s | 3.05 µs | 327.5k rows/sec |
Destination upload
Handing the mapped rows to the configured destination — the sum of the importer’s two internal phases, processing (1/2) and uploading (2/2). Only the three mapped columns go up, so the payload is a fraction of the source file. This is the largest stage at every size.
| Rows | Source file | Payload sent | Duration | Per row | Throughput |
|---|---|---|---|---|---|
| 100k | 17.32 MB | 5.40 MB | 8.1s | 81.02 µs | 12.3k rows/sec |
| 500k | 87.03 MB | 27.85 MB | 29.3s | 58.62 µs | 17.1k rows/sec |
| 1M | 174.16 MB | 55.90 MB | 51.2s | 51.22 µs | 19.5k rows/sec |
| 2M | 349.42 MB | 113.92 MB | 100.6s | 50.29 µs | 19.9k rows/sec |
End to end
All four stages together. Excludes idle time waiting on the user — picking the file, mapping columns, reviewing errors — so this is pipeline time rather than what a person experiences from file drop to done.
| Rows | Source file | Payload sent | Duration | Per row | Throughput |
|---|---|---|---|---|---|
| 100k | 17.32 MB | 5.40 MB | 9.3s | 92.78 µs | 10.8k rows/sec |
| 500k | 87.03 MB | 27.85 MB | 38.9s | 77.70 µs | 12.9k rows/sec |
| 1M | 174.16 MB | 55.90 MB | 73.7s | 73.75 µs | 13.6k rows/sec |
| 2M | 349.42 MB | 113.92 MB | 150.3s | 75.17 µs | 13.3k rows/sec |
What these figures do and don’t say
- 1One run per size, so there is no variance figure here. Treat each number as a single observation rather than a median.
- 2One machine, one network — a mid-range consumer laptop on shared office Wi-Fi. That makes these a realistic floor rather than a best case, but the upload stage in particular will move with your connection.
- 3One destination and one sheet shape: 3 typed columns and a single trivial transform. Wider sheets, heavier validation rules, and other destinations all scale differently.
- 4Idle time is excluded. Totals are the sum of the four stages and omit time spent waiting on the user, so they are not what a person experiences from file drop to done.
- 5These are client-reported timings from the browser-side importer, not server instrumentation.
- 6Column count moves timing more than file size does. A wide file at a given row count is consistently slower than a narrow one, so figures from this sheet will not transfer directly to a much wider schema.
Running your own numbers is the only way to be sure. Every plan includes a free Sandbox sheet you can point at your own files — see pricing for row limits by tier, or how large imports are handled for the mechanics behind these timings.