intermediate
Avro
8 min readLast updated: 2026-07-08
Overview
Avro is a row-based, binary serialization format. Learn why it is the standard choice for streaming message pipelines (like Apache Kafka) and schema registries.
What You Will Learn
In this lesson, you will learn:
- Avro Format: Row-based binary storage with JSON schema declarations.
- Use Cases: Why Avro is preferred for real-time streaming over Parquet.
- Spark Integration: Loading and writing Avro structures using the external package.
Detailed Concept Explanation
Unlike Parquet and ORC, which are columnar, Apache Avro is a row-based binary format.
Why Row-Based for Streaming?
- Fast Writes: Row-oriented formats write rows sequentially, making them ideal for writing incoming records one-by-one in real-time streaming systems like Apache Kafka. Columnar formats are slow for streaming because they require buffering data in memory to group columns together before writing.
- Strict Schema: Avro stores its schema as a JSON header, ensuring that reader and writer systems always agree on data types.
Code Examples
Input Dataset Preview
Below is the users logs dataset:
| userId | event |
|---|---|
| 1 | click |
| 2 | scroll |
Python (PySpark) Implementation
python
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("AvroTest").getOrCreate()
data = [(1, "click"), (2, "scroll")]
df = spark.createDataFrame(data, ["userId", "event"])
# Write to Avro
df.write.format("avro").mode("overwrite").save("logs.avro")
# Read Avro
read_df = spark.read.format("avro").load("logs.avro")
read_df.show()
Expected Output
text
+------+------+
|userId| event|
+------+------+
| 1| click|
| 2|scroll|
+------+------+
Execution Plan Diagram (Python & Scala)
Execution Plan Diagram
SparkSession.builder
createDataFrame
write.format(avro)
read.format(avro)
show()
Scala Implementation
scala
import org.apache.spark.sql.SparkSession
val spark = SparkSession.builder().appName("AvroScala").getOrCreate()
import spark.implicits._
val df = Seq((1, "click"), (2, "scroll")).toDF("userId", "event")
df.write.format("avro").mode("overwrite").save("logs.avro")
val readDF = spark.read.format("avro").load("logs.avro")
readDF.show()
Expected Output
text
+------+------+
|userId| event|
+------+------+
| 1| click|
| 2|scroll|
+------+------+
SQL Implementation
sql
-- Query Avro files directly using SQL path syntax
SELECT *
FROM avro.`logs.avro`
WHERE event = 'click';
Expected Output
Executing this SQL query returns:
| userId | event |
|---|---|
| 1 | click |
Common Mistakes
- Forgetting Spark Avro Package: In older Spark versions, Avro was not built-in. Running
spark.read.format("avro")without passing the Avro coordinate package coordinates (--packages org.apache.spark:spark-avro_2.12:<version>) would throw a class-not-found exception. Always ensure the package coordinate is loaded during cluster startup.
Best Practices
- Use for Kafka Ingestion: Use Avro as the serialization format when reading or writing streams from Apache Kafka to leverage Schema Registries.
Interview Perspective
What is the difference between Avro and Parquet? When should you use which?
Avro is a row-based format, making it fast for write-heavy, record-by-record streaming workloads (like Kafka ingestion). Parquet is a columnar format, making it fast for read-heavy, select-column batch analysis queries.