Storage Formats

Row vs Columnar Storagestorage formatshow physical layout drives write speed, scan speed and compression. Apache Avrostorage formatsrow-oriented binary format with schema evolution, the standard for Kafka. Apache Parquetstorage formatsthe default columnar format for data lakes and lakehouses. Apache ORCstorage formatscolumnar format from the Hive ecosystem with built-in indexes. Table FormatsSectionIceberg, Delta Lake and Hudi layered on top of file formats.

How data is laid out in files shapes the cost and speed of everything built on it. This section explains row and columnar formats and when to use each.


1. Overview

A storage format decides how records are turned into bytes on disk or in object storage. That choice drives file size, how fast queries run, whether schemas can evolve, and which tools can read the data. Formats split into two families. Row-oriented formats (CSV, JSON lines, Avro) store each record contiguously, which suits writing one event at a time and reading whole records. Columnar formats (Parquet, ORC) store each column contiguously, which suits analytics that scan a few columns across millions of rows and compress well because similar values sit together.

Where File Formats Sit in the Stack Query engines Spark, Trino, DuckDB, Snowflake Table formats Iceberg, Delta Lake, Hudi File formats Parquet, ORC, Avro, CSV, JSON Storage S3, ADLS, GCS, HDFS, local disk This section covers the yellow layer: how bytes for rows and columns are laid out.

File formats are the bottom of the analytical stack. Table formats such as Iceberg and Delta Lake add transactions, snapshots and schema management on top of collections of Parquet (or ORC, or Avro) files, and engines read through them.

2. How the Pages Fit Together

Read Row vs Columnar Storage first: it explains the physical layout difference that everything else follows from. Then read about the formats themselves. Avro is the usual choice for event streams and row-wise landing zones because of its schema evolution rules. Parquet is the default columnar format for lakes and lakehouses; ORC is its close relative from the Hive ecosystem. A typical pipeline lands Avro or JSON from Kafka, then compacts into Parquet under a table format for querying.

3. Choosing a Format

FormatLayoutSchemaCompressionTypical use
CSVRow, textNone (header only)Poor, not splittable when gzippedExchange with spreadsheets and legacy systems
JSON linesRow, textSelf-describing, untypedPoorAPIs, logs, semi-structured landing
AvroRow, binaryEmbedded, evolvableGood, splittable blocksKafka, CDC, row landing zones
ParquetColumnar, binaryEmbedded in footerExcellent, per columnLakehouse tables, analytics, ML features
ORCColumnar, binaryEmbeddedExcellent, built-in indexesHive and Trino warehouses

Rule of thumb: row formats for writing and transporting events, columnar formats for storing data you will query. Avoid CSV for anything internal; it has no types, ambiguous quoting and no schema.

4. Practical Concerns

Whatever the format, a few practices matter more than the choice itself. File size: aim for files in the range of roughly a hundred megabytes to a gigabyte for analytical data; thousands of tiny files overwhelm planners and object-store listing. Compression codec: Snappy and LZ4 favour speed, Zstandard offers a strong balance of ratio and speed, and gzip compresses well but is slower. Partitioning: split by a column queries usually filter on (often a date), but not so finely that each partition holds only a few rows. Schema discipline: decide how columns are added and renamed before the first consumer appears, because changing a format later means rewriting data.