The working decision tree
You've seen the players. Here's the decision tree I actually use, in the order it gets applied:
- Will a downstream pipeline read it? → Parquet (partitioned, zstd). This is 90% of the answer.
- Is the consumer a database that already has the data? → Don't write a file. Compute in the warehouse with SQL/dbt.
- Is the consumer a human with Excel? → CSV at the boundary, with a sidecar schema. Don't make it a pipeline stage.
- Is the data nested/log-shaped? → Newline-delimited JSON (NDJSON / JSONL). Compress with gzip or zstd.
- Is this short-term scratch between notebook stages? → Arrow IPC (Feather). Fastest load, because it skips Parquet's decode step — not because it skips compression. Reach it through Pandas'
df.to_feather(), which still defaults to an LZ4 frame (on one 400k-row frame: 6.5MB against 15.2MB uncompressed — your columns will give their own ratio), so you rarely wantcompression='uncompressed'. If you drop to raw PyArrow instead, read Track 3's Arrow lesson first — that path defaults the other way. - Is the data tiny and you want diffability? → CSV in version control. Past ~10MB, switch to Parquet.
What about HDF5, Avro, ORC, Iceberg, Delta Lake, Hudi?
Quick gloss:
- HDF5 — scientific data, hierarchical, predates the modern stack. Still used in physics/genomics. Don't pick it for new analytics work.
- Avro — row-oriented, common in Kafka pipelines. Fine for streams; Parquet for analytics-at-rest.
- ORC — Hadoop-era columnar competitor to Parquet. If you're not already in the ORC world, pick Parquet.
- Iceberg / Delta Lake / Hudi — table formats on top of Parquet. They add ACID transactions, schema evolution, time travel. Critical for warehouse-scale lakehouses; overkill for a single-machine pipeline. Learn them when you outgrow the file-tree approach.