Query Apache Arrow and Feather Files with SQL
Pandas and Polars often need a fast handoff format that preserves types. Apache Arrow is a language-agnostic columnar format for in-memory data, serialization, and data transport.1 Feather V2 is the Arrow IPC file format on disk, while Feather V1 is a legacy format distinct from Arrow IPC.2 DuckDB-WASM can ingest Arrow IPC streams and query Parquet files directly in the browser, so a DataFrame saved from pandas or Polars can become a SQL view without a separate conversion step.3
Arrow and Feather as inter-process data formats
Apache Arrow was designed around a columnar memory layout that supports fast sequential scans, random access, and zero-copy sharing across processes.1 Feather V2 stores Arrow tables using Arrow IPC, so .feather and .arrow files share the same serialized columnar layout; Feather V1 is the older, non-Arrow format that DuckDB cannot read directly.2
Schema preservation across tools
When a pipeline writes either file, the schema travels with the data, which is why DESCRIBE can report column names, types, and nullability without guessing. That is especially useful after a pandas or Polars step, because the file carries the difference between INTEGER, DOUBLE, TIMESTAMP, LIST, and STRUCT columns instead of asking DuckDB to infer everything from text. For teams that move data between Python, R, and SQL, this schema fidelity means a single file can serve as the authoritative exchange format without a separate schema registry or documentation step, which reduces the risk of type mismatches when a file crosses a language boundary.
Because Arrow stores both the logical type and the physical layout, an integer column arrives as a true integer rather than a text column DuckDB must re-parse, which keeps arithmetic and joins correct on the first query. The same fidelity applies to nested LIST and STRUCT columns, so a complex record written by Polars reads back with the same structure in DuckDB without a flattening step.
How the workbench loads Arrow and Feather files
DuckDB-WASM can insert Arrow IPC stream bytes through insertArrowFromIPCStream and can query Parquet files directly after registering a file.3 DuckDB's Arrow extension consumes and produces Arrow IPC files through read_arrow; filenames ending in .arrow or .arrows can be scanned directly.4 Because Feather V2 is Arrow IPC, .feather follows the same path after the browser exposes the file bytes to DuckDB-WASM. The Arrow schema embedded in the file defines columns, types, and nullability, so DESCRIBE orders reports the file schema rather than inferred SQL types. This direct schema mapping means you spend less time casting columns and more time analyzing data, which is especially helpful when the file originated from a Polars or pandas pipeline that already enforced strict types.
When to reach for Arrow instead of Parquet
Arrow IPC is a good fit when the next step needs fast serialization, while Parquet is a better fit for repeated selective queries because it compresses pages and carries row-group statistics.56 Arrow files appear most often as temporary exchange files between pipeline steps, whereas Parquet appears in data lakes and warehouse exports. If you received a .arrow or .feather file, it likely came from a tool that wanted fast read speed, such as a Polars pipeline step, a pandas to_feather() call, or DuckDB itself. The workbench handles both use cases: load the file you have, and the query experience is identical regardless of format.
Python and Polars workflows that produce Arrow files
When a pandas pipeline saves a checkpoint with df.to_feather('/tmp/checkpoint.feather'), it writes a Feather V2 Arrow IPC file that DuckDB-WASM can ingest as Arrow bytes. A Polars pipeline that writes df.write_ipc('/tmp/result.arrow') produces the same Arrow IPC format with a different extension, and DuckDB reads both identically without requiring you to rename files or convert between formats manually.
Verifying Python and Polars round trips
After loading, run DESCRIBE to confirm that column types survived the round-trip from your pipeline. If a timestamp became VARCHAR, the upstream export likely wrote text rather than an Arrow timestamp. If a nullable integer became DOUBLE, inspect the source DataFrame for nulls and consider converting to a nullable integer type before exporting. CapyToolkit keeps this inspection local in the browser, so you can validate pipeline outputs without installing DuckDB on the machine that produced the file.
Choosing between Parquet export and keeping Arrow format
For results you plan to load directly into a Python script, the Parquet file you download from the workbench is immediately readable with pd.read_parquet() or pl.read_parquet(). A round-trip from Arrow IPC in the workbench to Parquet export to Polars read is type-safe because all three steps share the Apache Arrow type system.
When to convert Arrow to Parquet for future queries
For files you will query repeatedly in future workbench sessions, converting Arrow to Parquet using the Export button produces a file that benefits from compression and row-group statistics on future selective WHERE queries.56 Parquet embeds per-row-group min/max statistics that Arrow IPC files lack. Load the Arrow file, run SELECT * FROM tablename, export as Parquet, and use the Parquet file as your new analytical baseline. Selective queries on sorted columns can run faster because Parquet readers can discard row groups that cannot match the filter. The Export button produces a type-safe Arrow-to-Parquet round trip you can confirm locally before wiring it into a pipeline that depends on it.
When to use this
Use this when you have a .arrow or .feather file produced by pandas, Polars, R, or another Arrow-native tool and want to run SQL aggregations or filters on it without installing DuckDB locally.
Examples
Inspect the schema of an Arrow file
DESCRIBE orders;
Arrow embeds an exact schema in the file header, so `DESCRIBE` returns precise types without inference.
Aggregate a Feather file by a dimension
SELECT product_category,
AVG(unit_price) AS avg_price,
COUNT(*) AS n
FROM products
GROUP BY product_category
ORDER BY avg_price DESC; .feather files are Arrow IPC files and query identically to .arrow files.
Filter and export a subset to Parquet
SELECT * FROM events WHERE event_date >= '2026-03-01' AND user_segment = 'paid';
After running this query, use the Export button to download the filtered result as Parquet.
Access a struct column field
SELECT metadata.source,
metadata.version,
COUNT(*) AS n
FROM records
GROUP BY 1, 2; Arrow struct columns are accessible via dot notation, the same as Parquet nested types.
- 1.
Apache Arrow Project, "Arrow Columnar Format," arrow.apache.org, version 1.5, accessed June 2026. https://arrow.apache.org/docs/format/Columnar.html
- 2.
Apache Arrow Project, "Feather File Format," arrow.apache.org, v24.0.0, accessed June 2026. https://arrow.apache.org/docs/python/feather.html
- 3.
DuckDB Foundation, "Data Ingestion," duckdb.org, accessed June 2026. https://duckdb.org/docs/current/clients/wasm/data_ingestion
- 4.
Pedro Holanda et al., "Arrow IPC Support in DuckDB," duckdb.org, May 23 2025. https://duckdb.org/2025/05/23/arrow-ipc-support-in-duckdb
- 5.
Apache Parquet Project, "Compression," parquet.apache.org, last modified February 24 2026. https://parquet.apache.org/docs/file-format/data-pages/compression/
- 6.
Cloudera, "Predicate Pushdown in Parquet," docs-archive.cloudera.com, 6.3.x, accessed June 2026. https://docs-archive.cloudera.com/documentation/enterprise/6/6.3/topics/cdh_ig_predicate_pushdown_parquet.html