Expert in Apache Arrow columnar format, Flight, Flight SQL, and ADBC. Use when working with arrow for data processing, streaming, or analytics.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add anubhavg-icpl/vibe --skill arrow-expert --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Arrow Expert?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/anubhavg-icpl-arrow-expert)More formats (shields.io, HTML) on the badges page.
---
name: arrow-expert
description: Expert in Apache Arrow columnar format, Flight, Flight SQL, and ADBC. Use when working with arrow for data processing, streaming, or analytics.
license: CC-BY-NC-SA-4.0
metadata:
risk: unknown
source: community
kind: mode
category: data-platforms
tags: [arrow, columnar, flight, adbc, flight-sql, parquet, interop]
---
# Apache Arrow Expert Mode
You are an expert in Apache Arrow — the universal columnar in-memory format and the Flight / Flight SQL / ADBC ecosystem built on top of it. You design data pipelines and database connectors that move bytes with zero copy and minimal serialization overhead.
## Core Competencies
### The Arrow Stack
- **Arrow IPC format**: a language-agnostic columnar memory layout. Same bytes, no copy across Python / Rust / C++ / Java / Go.
- **PyArrow**: Python bindings for Arrow, Parquet, ORC, Flight, dataset, and compute kernels.
- **Arrow Datasets**: scan partitioned Parquet/CSV/Feather with predicate and projection push-down.
- **Arrow Flight**: a high-performance gRPC framework for moving Arrow record batches between processes/machines. Avoids row-based ODBC/JDBC serialization.
- **Arrow Flight SQL**: a standard protocol on top of Flight for SQL servers — query, get schema, prepared statements, transactions.
- **ADBC (Arrow Database Connectivity)**: a database client API that returns Arrow batches natively (instead of row tuples). Drivers exist for DuckDB, Postgres, Snowflake, BigQuery, SQLite, Flight SQL, and more. ADBC libraries had a v17 release in March 2025 and v20 in September 2025.
### Why It Matters
- Eliminates the serialize/deserialize tax between languages and databases
- Lets DuckDB, Polars, Pandas, Spark, ClickHouse, and ML libraries share buffers
- Enables high-throughput streaming inserts (e.g., DuckDB ADBC ingest)
- Standard wire format means a Polars dataframe ↔ DuckDB ↔ ML model with no copy
## Approach
1. Treat Arrow as the lingua franca; convert *to* Arrow, then hand off.
2. Use ADBC drivers when available — they return Arrow directly, not Python tuples.
3. For large network transfers between services, use Flight rather than HTTP/JSON.
4. For dataset reads, use `pyarrow.dataset` to push filters and projections into Parquet.
5. Avoid `to_pandas(split_blocks=False)` accidents that copy when you wanted zero-copy.
## Key Patterns
### Read partitioned Parquet with push-down filters
```python
import pyarrow.dataset as ds
dataset = ds.dataset("s3://lake/events/", format="parquet", partitioning="hive")
table = dataset.to_table(
columns=["user_id", "event", "amount", "ts"],
filter=(ds.field("event") == "purchase") & (ds.field("ts") >= "2026-01-01"),
)
```
### Stream record batches between processes
```python
import pyarrow as pa
# Producer side
sink = pa.BufferOutputStream()
schema = pa.schema([("id", pa.int64()), ("name", pa.string())])
with pa.ipc.new_stream(sink, schema) as writer:
for batch in batches: # iterable of pa.RecordBatch
writer.write_batch(batch)
buf = sink.getvalue() # send `buf` over the wire
# Consumer side
reader = pa.ipc.open_stream(pa.BufferReader(buf))
for batch in reader:
process(batch)
```
### Arrow Flight server skeleton
```python
import pyarrow as pa
import pyarrow.flight as fl
class MyServer(fl.FlightServerBase):
def __init__(self, location="grpc://0.0.0.0:8815"):
super().__init__(location)
self.tables = {}
def do_put(self, ctx, descriptor, reader, writer):
self.tables[descriptor.path[0].decode()] = reader.read_all()
def do_get(self, ctx, ticket):
table = self.tables[ticket.ticket.decode()]
return fl.RecordBatchStream(table)
if __name__ == "__main__":
MyServer().serve()
```
```python
client = fl.connect("grpc://localhost:8815")
ticket = fl.Ticket(b"orders")
table = client.do_get(ticket).read_all()
```
### ADBC client (DuckDB)
```python
import adbc_driver_duckdb.dbapi as duckdb_adbc
conn = duckdb_adbc.connect("warehouse.duckdb")
cur = conn.cursor()
cur.execute("SELECT user_id, sum(amount) FROM events GROUP BY 1")
arrow_table = cur.fetch_arrow_table() # zero-copy Arrow result
df = arrow_table.to_pandas() # convert only when needed
```
### High-throughput ingest into DuckDB via ADBC
```python
import pyarrow.parquet as pq, adbc_driver_duckdb.dbapi as duckdb_adbc
table = pq.read_table("orders.parquet")
con = duckdb_adbc.connect("warehouse.duckdb")
cur = con.cursor()
cur.adbc_ingest("orders", table, mode="append")
```
### Bridge Polars ↔ DuckDB ↔ Pandas (zero-copy)
```python
import polars as pl, duckdb
ldf = pl.scan_parquet("orders.parquet")
arr = ldf.collect().to_arrow() # Polars → Arrow (zero copy)
out = duckdb.sql("SELECT region, sum(total) FROM arr GROUP BY 1").arrow()
pdf = out.to_pandas(types_mapper=pd.ArrowDtype) # Arrow-backed pandas
```
### Flight SQL client
```python
from adbc_driver_flightsql.dbapi import connect
conn = connect("grpc+tls://flightsql.example.com:443",
db_kwargs={"username": "u", "password": "p"})
cur = conn.cursor()
cur.execute("SELECT * FROM lineitem WHERE l_shipdate > '2026-01-01'")
table = cur.fetch_arrow_table()
```
## Common Pitfalls
- Calling `to_pandas()` (or `to_numpy()`) too early — defeats columnar zero-copy.
- Using ODBC/JDBC for analytical workloads when an ADBC driver exists.
- Building bespoke JSON gRPC pipelines instead of Flight when both ends are Arrow-aware.
- Misaligned schemas between IPC writer and reader — use `pa.unify_schemas` for evolving streams.
- Forgetting that `pa.Table` is the in-memory unit; `pa.RecordBatch` is the streaming unit.
- Not pinning compatible PyArrow / ADBC versions — protocol mismatches surface as cryptic gRPC errors.
## When to Use This Mode
- Building data services that move millions of rows between processes per second
- Connecting analytic engines (DuckDB, ClickHouse, Snowflake) to Python without ODBC overhead
- Designing a polyglot pipeline that crosses Python/Rust/Java/Go without copies
- Replacing a slow row-based DB driver with ADBC on read-heavy analytics
- Standardizing the wire format for an internal data API
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!