title: 'Query Federation' sidebar_label: 'Query Federation' description: 'Learn how to use federated SQL queries in Spice.ai Open Source' sidebar_position: 1 pagination_prev: null pagination_next: null tags:
import DocCardList from '@theme/DocCardList';
Spice provides a high-performance SQL query engine built on Apache DataFusion, supporting query federation across multiple data sources including databases (PostgreSQL, MySQL), data warehouses (Databricks, Snowflake, BigQuery), and data lakes (S3, MinIO).

For a full list of supported sources, see Data Connectors (opens in a new tab).
Query federation is useful when:
Query data from PostgreSQL and S3 through a single SQL interface:
Spice supports multiple ways to execute queries:
| Protocol | Endpoint | Description |
|---|---|---|
| HTTP | /v1/sql | Execute SQL queries over HTTP |
| Arrow Flight SQL | grpc://localhost:50051 | High-performance Arrow-native queries |
| JDBC/ODBC | Flight SQL compatible | Connect from BI tools and applications |
| ADBC | Flight SQL driver | Arrow Database Connectivity |
Execute a query using the HTTP API:
Connect using Arrow Flight SQL for high-performance data transfer:
Use the Spice CLI for interactive queries:
To start using federated queries in Spice, follow these steps from the Federated SQL Query (opens in a new tab) cookbook recipe, which joins NYC taxi trips stored in S3 with taxi zone names stored in PostgreSQL:
Step 1. Install Spice by following the installation instructions (opens in a new tab).
Step 2. Clone the Spice Cookbook repository and navigate to the federation directory.
Step 3. Start a local PostgreSQL instance and load the NYC taxi zone lookup table. This step requires Docker (opens in a new tab).
make starts PostgreSQL in Docker on host port 15432, loads the taxi_zones table, and prints its row count:
Step 4. Store the PostgreSQL password. Run this command in the federation directory.
The password is written to a local .env file, which the Spice runtime reads on startup.
Step 5. Start the Spice runtime.
The recipe's spicepod.yaml defines four datasets:
| Dataset | Data |
|---|---|
taxi_trips | 2,964,624 NYC yellow taxi trips, stored as Parquet in public S3 |
taxi_zones | NYC taxi zone lookup table, stored in PostgreSQL |
taxi_trips_accelerated | taxi_trips, accelerated locally in memory with Arrow |
taxi_zones_accelerated | taxi_zones, accelerated locally in memory with Arrow |
Wait for Spice runtime is ready! in the runtime output before querying. Loading the accelerated copy of taxi_trips takes several seconds, depending on network speed.
Step 6. In another terminal, start the Spice SQL REPL.
Join trips in S3 with zone names in PostgreSQL to find the 10 busiest pickup zones. The trip data uses mixed-case column names, so "PULocationID" is quoted.
Step 7. Run the same join against the locally accelerated datasets.
The query returns the same 10 rows without contacting S3 or PostgreSQL:
Query times vary between runs, and federated query times depend on network latency to S3.
Step 8. Stop the Spice runtime with Ctrl+C. Then stop PostgreSQL and remove its container and volume.
The join in step 6 reads trips from S3 and zones from PostgreSQL at query time, so its response time includes network latency and data transfer.
Step 7 runs the same join against copies of both datasets materialized locally with Data Accelerators (opens in a new tab). Because the query reads only local data, it returns the same rows in milliseconds instead of seconds.
:::warning[Limitations]
:::