Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Parquet, ORC, and Avro File Formats

By Kokil Thapa | Last reviewed: September 2026

Choosing among Parquet, ORC, and Avro file formats is one of the first decisions in a modern data pipeline. Row-oriented CSV and JSON work for small exports. They fall apart once you scan terabytes for a handful of columns. Columnar formats like Parquet and ORC store data by column, so engines read only what a query needs. Avro takes a different path: compact binary rows with an embedded schema contract, built for streaming and cross-language exchange. This guide compares all three on real engineering criteria—read patterns, schema changes, tooling, and storage cost—so you can pick the right default before your lake fills up. If you are wiring exports from a REST API or ETL pipeline, the format choice affects every downstream query.

What Are Parquet, ORC, and Avro File Formats?

All three are open, Apache-licensed binary formats. They replace plain CSV for production data work. Each encodes type information, supports compression, and integrates with object storage like S3 or MinIO. The split is structural and operational—not cosmetic.

Parquet is a columnar format. Values for one column sit together in row groups and pages. Predicate pushdown skips entire blocks when a filter does not match. It is the de facto standard for data lakes, Spark, Presto/Trino, DuckDB, BigQuery external tables, and AWS Athena.

ORC (Optimized Row Columnar) is also columnar. It was built for Apache Hive and Tez on Hadoop. ORC adds lightweight indexes, bloom filters, and stripe-level statistics. Hive and some Cloudera stacks still prefer it.

Avro is row-oriented. Each file carries a JSON schema in the header. Records serialize as compact binary rows. Avro shines in Kafka, Flink, and any pipeline where writers and readers evolve independently and schemas must stay compatible.

Row vs Columnar LayoutRow-Oriented (Avro, CSV)Row 1: id | name | amount | dateRow 2: id | name | amount | dateRow 3: id | name | amount | dateColumnar (Parquet, ORC)idnameamtdtFull row read per recordRead only columns in SELECTAnalytics on 2 of 50 columns: columnar wins by 10-100x I/OParquet and ORC skip untouched column chunks
Parquet, ORC, and Avro file formats differ in layout—columnar stores values by field; row formats read entire records.

On a production Laravel app I maintain, nightly order exports land in S3 as Parquet. A reporting job in DuckDB scans millions of rows but touches only five columns. The same export as CSV would cost more storage and far more scan time. That pattern repeats across eCommerce platforms with large order histories and any system that outgrows spreadsheet exports.

How Do Parquet, ORC, and Avro Compare on Performance and Features?

Benchmarks vary by workload, but the trade-offs are stable. Columnar formats win on analytical SELECT with filters and aggregations. Avro wins on append-heavy ingest and schema-safe messaging. ORC and Parquet overlap heavily; engine support usually breaks the tie.

CriteriaParquetORCAvro
LayoutColumnar (row groups + pages)Columnar (stripes)Row-oriented blocks
Best forData lakes, ad-hoc SQL, ML featuresHive, Tez, legacy HadoopKafka, Flink, RPC payloads
Schema in fileFooter metadata (Thrift)Footer metadataJSON schema in header
Schema evolutionAdd columns; limited renamesSimilar to ParquetStrong reader/writer compatibility rules
CompressionSnappy, GZIP, ZSTD, LZ4Snappy, ZLIB, LZ4, ZSTDDeflate, Snappy, ZSTD
Predicate pushdownExcellent (statistics per page)Excellent (stripe indexes)Minimal (full row scan)
SplitabilityYes (row-group boundaries)Yes (stripe boundaries)Yes (sync markers)
Typical enginesSpark, DuckDB, Athena, BigQueryHive, Presto (limited)Kafka Connect, Spark streaming
Human readableNo (use parquet-tools)No (use orc-tools)No (schema JSON is readable)

Verdict: Default to Parquet for new lake tables unless your stack is Hive-native—then evaluate ORC. Use Avro for event streams and service-to-service binary exchange, not for warehouse fact tables.

Compression and file size

All three support Snappy for fast compression with modest ratios. ZSTD gives better ratios at higher CPU cost. Parquet and ORC compress repeated column values aggressively because similar types sit together. Avro compresses well on repetitive row data but lacks column-level encoding tricks like dictionary encoding on low-cardinality fields.

Schema evolution in practice

Avro formalizes compatibility: backward (new schema reads old data), forward, and full. Kafka Schema Registry enforces these rules. Parquet handles added columns gracefully—old readers ignore new fields. Removed or renamed columns need migration discipline. ORC behaves similarly to Parquet for Hive metastore workflows.

Format Selection FlowNew data pipeline?Streaming or RPC?Use AvroKafka, schema registryBatch analytics?Hive primary?Use ORCUse Parquet
Decision flow for Parquet, ORC, and Avro file formats—stream workloads favor Avro; SQL lakes default to Parquet.

How Do You Read and Write Parquet, ORC, and Avro in Code?

Most teams touch these formats through Python, Java, or SQL engines—not raw bytes. Below are minimal, copy-pasteable patterns. Install dependencies in a virtual environment; pin versions in production pipelines.

Python with PyArrow (Parquet)

pip install pyarrow pandas

import pandas as pd

df = pd.DataFrame({
    "order_id": [1001, 1002, 1003],
    "amount_npr": [1500.00, 3200.50, 890.00],
    "status": ["paid", "paid", "refunded"],
})

df.to_parquet(
    "orders.parquet",
    engine="pyarrow",
    compression="snappy",
    index=False,
)

loaded = pd.read_parquet("orders.parquet", columns=["order_id", "amount_npr"])
print(loaded.head())

PyArrow is the standard Parquet bridge in Python. DuckDB can query the same file without loading it fully into memory:

duckdb.sql("""
    SELECT status, SUM(amount_npr) AS total
    FROM 'orders.parquet'
    GROUP BY status
""").show()

Java with Avro (schema-first)

Define a schema in JSON, generate classes, then serialize. Avro expects the schema at write time and embeds it in every file.

{
  "type": "record",
  "name": "OrderEvent",
  "namespace": "com.example",
  "fields": [
    {"name": "order_id", "type": "long"},
    {"name": "amount_npr", "type": "double"},
    {"name": "event_time", "type": "long", "logicalType": "timestamp-millis"}
  ]
}

Official Avro Java docs cover DatumWriter and DatumReader usage. In Kafka Connect, the Avro converter pairs with Confluent Schema Registry for centralized schema IDs.

Hive / Spark ORC

CREATE TABLE sales_orc (
  sale_id BIGINT,
  product STRING,
  revenue DOUBLE
)
STORED AS ORC
TBLPROPERTIES ('orc.compress'='SNAPPY');

INSERT OVERWRITE TABLE sales_orc
SELECT sale_id, product, revenue FROM sales_staging;

Spark reads all three natively:

val parquetDf = spark.read.parquet("s3://bucket/lake/orders/")
val orcDf     = spark.read.orc("s3://bucket/hive/sales_orc/")
val avroDf    = spark.read.format("avro").load("s3://bucket/events/")

When a web app exports JSON logs, converting to Parquet before analytics cuts storage and query cost. A JSON formatter and validator helps debug source payloads before you batch-convert them.

Lake Ingest PipelineLaravel AppAPI + exportsETL JobCSV to ParquetS3 BucketObject storageDuckDBSQL analyticsParquet row groups enable parallel readsRow Group 1cols + statsRow Group 2cols + statsRow Group 3cols + statsMin/max stats skip groups that fail WHERE filters
Typical Parquet pipeline from application export through object storage to column-pruned SQL queries.

What Mistakes Do Teams Make With Parquet, ORC, and Avro?

Format choice is only half the battle. Bad partitioning and tiny files destroy performance on every format. These errors show up repeatedly on client analytics projects and internal reporting jobs.

  1. Using Avro for warehouse fact tables. Full-row scans on wide Avro files waste I/O. Convert stream data to Parquet in a batch layer (Spark, dbt, or AWS Glue).
  2. Tiny files (the "small file problem"). Thousands of 100 KB Parquet files add metadata overhead and slow listing. Target 128 MB–1 GB per file; compact with coalesce or scheduled merge jobs.
  3. Wrong partition keys. Partitioning by high-cardinality UUID creates millions of directories. Partition by date or region—columns that match common filters.
  4. Ignoring compression choice. Snappy is the safe default for interactive queries. Use ZSTD for cold archival tiers where CPU is cheaper than storage (often Rs 2–4 per GB/month on object storage, ~USD 0.015–0.023).
  5. Mixing formats in one table without reason. Keep raw Avro in a bronze zone; standardize silver/gold layers on Parquet for one SQL dialect.
  6. Skipping schema documentation. Parquet embeds types but not business meaning. Maintain a data catalog or OpenAPI-style field glossary alongside files.

Large binary attachments belong in object storage with references in your database—not inside Parquet columns. Patterns from Laravel S3 file storage setup and multi-disk upload configuration apply to export staging buckets too. Version large schema files in Git; treat them like application code. For very large binary artefacts in repos, see Git LFS for large files.

Log analytics is a related discipline. Server access logs are row-oriented text. Converting parsed logs to Parquet unlocks fast aggregation—the same principle behind SEO log file analysis for technical wins.

CSV vs Parquet Query CostBefore: CSV on S3500 GB total sizeScan: all columnsQuery time: 12 minCost: high egressEvery SELECT readsfull row widthmigrateAfter: Parquet120 GB (Snappy)Scan: 3 of 40 colsQuery time: 45 secCost: lower I/OColumn pruning +page statistics
Migrating from CSV to Parquet typically cuts storage and scan I/O for column-selective analytics workloads.

How Do Parquet, ORC, and Avro Fit Into a Modern Data Stack in 2026?

Cloud warehouses still accept CSV uploads for ad-hoc work. Production pipelines standardize on open columnar formats. The 2026 landscape favors Parquet as the interchange format between lakes and query engines.

Data lakes on S3/MinIO: Parquet with Hive-style partitioning (year=2026/month=09/) is the common pattern. AWS Athena and Apache Iceberg/Delta Lake both sit comfortably on Parquet files. Iceberg adds ACID transactions; the underlying file format remains Parquet in most deployments.

Streaming: Kafka producers often emit Avro or Protobuf. A Flink or Spark Streaming job sinks micro-batches into Parquet for the lake. Keep Avro in the hot path; land Parquet in the cold path.

ML feature stores: Training pipelines read Parquet directly into Pandas, Polars, or TensorFlow. Column selection maps cleanly to feature subsets.

PHP/Laravel boundaries: Laravel apps rarely write Parquet natively. The practical pattern is export CSV or JSON to a queue, then let a Python or Spark worker convert to Parquet on a schedule. For enterprise applications with reporting requirements, define the contract at the export layer and document column types. A custom software pipeline can automate the handoff.

Directory platforms with heavy listing data—like multi-vendor business directories—benefit from separating operational MySQL rows from analytical Parquet snapshots. Operational queries stay fast on normalized tables. BI dashboards scan denormalized Parquet without touching production DB load.

External references worth bookmarking: the Apache Parquet documentation, the Apache ORC specification, and the Apache Avro specification. These are the authoritative sources for encoding rules and compatibility notes.

Tooling cheat sheet

  • parquet-tools or parquet-cli — inspect schema, row groups, and column stats from the shell.
  • DuckDB — local SQL on Parquet without a cluster; ideal for validation scripts.
  • Apache Arrow — in-memory columnar layer; zero-copy reads between Parquet and Pandas.
  • Confluent Schema Registry — required infrastructure when Avro schemas evolve in Kafka.
  • AWS Glue / Spark — managed conversion from JSON, CSV, or Avro to Parquet at scale.

Sync and backup workflows for large file sets on Linux servers overlap with data movement concerns. rsync for efficient file sync remains relevant when copying Parquet directories between on-prem staging and cloud buckets. Test integrity with row counts and checksums after every transfer.

Key Takeaways

  • Default new analytics lakes to Parquet unless your org is Hive-locked—then use ORC.
  • Use Avro for Kafka topics and RPC payloads where schema evolution matters more than column pruning.
  • Target 128 MB–1 GB Parquet files; partition by low-cardinality filter columns like date or country.
  • Pair Snappy compression with interactive SQL; switch to ZSTD for cold archival tiers.
  • Convert stream Avro to batch Parquet in a medallion pipeline—bronze raw, silver typed, gold aggregated.
  • Inspect files with parquet-tools or DuckDB before trusting production dashboards built on new exports.

People Also Ask

Is Parquet better than CSV for data storage?

Yes, for analytical workloads. Parquet stores typed columns with compression and embedded statistics. CSV is row text with no schema enforcement. A query that needs three columns from a fifty-column dataset reads roughly three-fiftieths of the data in Parquet but the full file in CSV. CSV still wins for human editing and universal tool support.

Can Spark read all three formats?

Spark reads Parquet, ORC, and Avro natively via spark.read.parquet(), spark.read.orc(), and the Avro data source. Parquet is the default recommendation in Databricks and most cloud Spark offerings. ORC requires the Hive ORC implementation on the classpath. Avro needs the spark-avro package in some distributions.

Does Avro support schema evolution?

Avro has first-class schema evolution with explicit compatibility modes. Writers embed the schema in each file. Readers resolve differences using Avro's resolution rules—field reorder, optional fields, and promoted types. This is why Kafka ecosystems standardize on Avro plus Schema Registry rather than raw JSON.

Which format does AWS Athena prefer?

Athena queries Parquet and ORC efficiently with predicate pushdown to S3. Parquet is the documented best practice for new Athena tables. Create external tables with STORED AS PARQUET and partition by common filter columns. Avro is supported but less common for warehouse-style queries.

Pick the Right Format Before Your Data Grows

Parquet, ORC, and Avro file formats are not interchangeable labels. They encode different read/write assumptions that stick with you for years. Parquet owns the analytics lake. ORC serves Hive estates. Avro carries events across services. Match the format to your query engine and ingest pattern—not to whatever format appeared in a tutorial.

If you are designing exports, reporting pipelines, or lake storage for a web application, map the decision early. Wrong formats cost real money in S3 scans and engineer time. Need help architecting data handoffs from a Laravel or API backend to an analytics layer? Contact us to discuss pipeline design, or explore AI integration and automation services for scheduled conversion jobs. Browse the portfolio for examples of production systems that combine operational apps with structured reporting, and visit the developer tools section for utilities that help validate JSON and binary payloads before they enter your lake.

Frequently Asked Questions

Open, Apache-licensed binary formats that replace plain CSV for production data work. Parquet and ORC are columnar; Avro is row-oriented with a JSON schema embedded in each file header.

Yes for analytical workloads. Parquet reads only the columns a query needs, with compression and embedded statistics. CSV still wins when humans must edit files or every tool must open them unchanged.

Parquet. Athena queries Parquet and ORC efficiently on S3, but Parquet is the documented best practice for new external tables with predicate pushdown and partition pruning.

Default to Parquet for new analytics lakes unless your stack is Hive-native, then evaluate ORC. Parquet is the de facto standard for Spark, DuckDB, Presto or Trino, BigQuery external tables, and AWS Athena. ORC fits Apache Hive and Tez estates where stripe indexes and bloom filters already integrate with your metastore. Use Avro for Kafka streams, Flink ingest, and service-to-service payloads where schema evolution matters more than column pruning. Match the format to your query engine and ingest pattern, not tutorial defaults.

Columnar formats like Parquet and ORC store all values for one field together in row groups or stripes, so a query needing five columns from a fifty-column dataset reads roughly one-tenth of the I/O. Row-oriented Avro stores complete records as compact binary blocks, which suits append-heavy streaming but forces full-row scans on wide analytical queries. Predicate pushdown is excellent on Parquet and ORC page or stripe statistics; Avro offers minimal pushdown because filters must walk entire rows. That structural split drives every downstream performance trade-off.

Yes. Spark reads all three through spark.read.parquet(), spark.read.orc(), and the Avro data source without custom parsers. Parquet is the default recommendation in Databricks and most cloud Spark offerings. ORC requires the Hive ORC implementation on the classpath. Avro may need the spark-avro package in some distributions. For lake fact tables, Parquet is the usual choice; keep Avro on the streaming path and convert in a batch layer when warehouse-style SQL is the goal.

Avro has first-class schema evolution with explicit backward, forward, and full compatibility modes. Writers embed the schema in every file header, and readers resolve differences using Avro resolution rules for field reorder, optional fields, and promoted types. Kafka ecosystems standardize on Avro plus Confluent Schema Registry rather than raw JSON for that reason. Parquet handles added columns gracefully because old readers ignore new fields, but removed or renamed columns need migration discipline. ORC behaves similarly to Parquet in Hive metastore workflows.

Snappy is the safe default for interactive SQL because it balances speed and modest compression ratios on both Parquet and ORC. ZSTD gives better ratios at higher CPU cost and suits cold archival tiers where storage is cheaper than compute, often around Rs 2 to 4 per GB per month on object storage, roughly USD 0.015 to 0.023. All three formats support Snappy; Parquet and ORC also accept GZIP, ZSTD, and LZ4 variants depending on engine support. Avro commonly uses Deflate, Snappy, or ZSTD on repetitive row data.

Thousands of tiny Parquet files, often around 100 KB each, add metadata overhead, slow S3 listing, and hurt query planners on every format. Target roughly 128 MB to 1 GB per file for lake tables. Compact with Spark coalesce, scheduled merge jobs, or AWS Glue jobs after high-frequency micro-batch writes. Wrong partitioning by high-cardinality UUIDs creates millions of directories and makes the problem worse. Partition by low-cardinality filter columns like date or region that match common WHERE clauses instead.

No. Avro is row-oriented, so wide fact-table queries scan entire records even when SQL needs a handful of columns. That wastes I/O on warehouse workloads. Avro excels in Kafka producers, Flink pipelines, and RPC payloads where writers and readers evolve independently. Convert stream Avro to Parquet in a batch layer using Spark, dbt, or AWS Glue before building silver or gold analytics tables. Keep raw Avro in a bronze zone; standardize typed lake layers on Parquet for one SQL dialect across dashboards.

Use Hive-style paths such as year=2026/month=09/ on S3 or MinIO, keyed on columns that appear in common filters like date, month, or country. Avoid high-cardinality keys such as order UUID, which explode into millions of prefixes and destroy list performance. Partitioning complements column pruning: engines skip directories that fail predicate pushdown on stripe or page statistics. Pair sensible partition keys with file sizes around 128 MB to 1 GB so each partition folder holds a manageable number of files, not thousands of tiny shards.

Laravel rarely writes Parquet natively. The practical pattern on production apps is nightly export of CSV or JSON to a queue or staging bucket, then a scheduled Python PyArrow worker or Spark job converts to Parquet on S3. Define column types and business meaning at the export contract layer because Parquet embeds types but not semantic documentation. On a Laravel app I maintain, order exports land as Parquet while DuckDB reporting scans millions of rows but touches only five columns, avoiding production database load.

Install PyArrow in a virtual environment and pin versions in production pipelines. Pandas writes typed columns with Snappy compression via df.to_parquet() and reads selective columns with read_parquet(columns=[...]) for column pruning without loading the full dataset. DuckDB queries the same file directly with SQL, aggregating grouped metrics without pulling everything into memory first. PyArrow is the standard Parquet bridge in Python; Apache Arrow provides the in-memory columnar layer for zero-copy handoffs between Parquet and Pandas during validation scripts.

parquet-tools or parquet-cli inspect schema, row groups, and column statistics from the shell on Parquet files. DuckDB runs local SQL against Parquet without a cluster, ideal for row-count checks before BI tools connect. ORC has orc-tools for similar inspection. Avro schema JSON in the file header is human readable even though record payloads are binary. After rsync or bucket copies between staging and cloud, verify integrity with row counts and checksums. Inspect new exports before production dashboards depend on them.

Kafka producers often emit Avro or Protobuf on the hot path where schema compatibility is enforced, frequently through Confluent Schema Registry. A Flink or Spark Streaming job sinks micro-batches into Parquet for the cold analytics path on S3 or MinIO. Medallion design keeps bronze raw Avro, silver typed Parquet, and gold aggregated Parquet so one SQL dialect serves Athena, DuckDB, and ML feature pipelines. Iceberg and Delta Lake add ACID transactions atop Parquet in most deployments. Convert stream Avro to batch Parquet rather than querying Avro as warehouse fact tables.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: