AirMettle Select — Faster queries without a data warehouse
High-performance object queries
no warehouse required

Query faster.
Skip the warehouse.

AirMettle Select prepares data in object storage once, then runs parallel SQL queries where the data already lives—built for a faster path than conventional serverless object-storage analytics, without loading a separate data warehouse first.

Try it on Azure ↗
Transparent benchmarks: public datasets, reviewable SQL, and direct performance comparisons.
select.airmettle / workspace connected
{{ demoLabel }}{{ demoObject }}
{{ ln.no }} {{ ln.text }}
✓ {{ demoStatus }}{{ demoFoot }} {{ demoTime }}
REST APICLICSV · JSON/JSONL · GZIPObject storage

Product Highlights

  • Best forFast, selective SQL over operational data already in object storage.
  • Direct formatsQuery CSV, JSON, JSON Lines, and GZIP-compressed inputs in place.
  • Data stays yoursSource objects and acceleration metadata remain in customer-controlled storage.
{{ s.big }}
{{ s.label }}
Why AirMettle Select is faster

A faster query path leaves out the warehouse detour.

Mainstream stacks copy, transform, load, and rescan data before returning an answer. AirMettle Select prepares compact metadata once, analyzes the source data in place, and streams only the selected output.

The usual warehouse path MORE HOPS

Stage first. Query later.

OBJECTSsource
→
ETL / LOADstage
→
WAREHOUSEload
→
QUERYscan
DATA COPIED PIPELINE REQUIRED EXTRA COMPUTE
The AirMettle Select fast path DIRECT

Prepare once. Query directly.

OBJECT + METADATAprepare once
→
PARALLEL SQLselect
→
RESULTselected only
NO WAREHOUSE PARALLEL READS ANALYZE IN PLACE
Measured across real-world workloads. Explore operational investigations, analytical benchmarks, and compressed-log queries using public datasets.
Performance by architecture

High performance without another data platform.

{{ st.no }}
{{ st.title }}
{{ st.body }}
Why AirMettle Select wins

A faster query engine, without the warehouse overhead.

{{ c.k }}
{{ c.t }}
{{ c.d }}
Input format coverage

Query more of what is already in object storage.

Query CSV, JSON, JSON Lines, and GZIP-compressed inputs today. Contact us for early access to Parquet, HDF5, and NetCDF4.

{{ f.kind }} {{ f.availability }} {{ f.availability }}

{{ f.title }}

{{ f.description }}

{{ f.supportedBy }}

{{ f.project }}

Confirmation of financial support from the Department of Energy and NOAA does not imply a formal endorsement of the products by these agencies.

Contact for early access

Background metadata generation.

For subscribed buckets, metadata is prepared automatically in the background as data arrives from your existing processes—no manual preparation step required.

AUTO
New object arrives AirMettle Select detects it, prepares the query metadata, and keeps the object ready for fast selection.
See the advantage

Query faster.
Leave the warehouse out.

Bring a representative object and query. See how AirMettle Select fits your analytics path through its Azure Marketplace listing.

Try it on Azure ↗
How it works

A selection layer between stored objects and useful answers.

Keep source data in object storage. AirMettle Select creates compact sidecar metadata in the same customer-controlled storage boundary, analyzes the original objects in place, and returns only the records your application needs.

{{ a.k }}
{{ a.t }}
{{ a.d }}
Source objects + sidecar metadata remain in customer-controlled storageOnly selected output continues downstream
Official documentation

From setup to your first query.

Follow the maintained guides for connecting resources, preparing objects, and querying with AirMettle Select.

Read the docs ↗
AirMettle Select quickstart

Run your first query in five minutes.

AirMettle Select lets you run SQL queries directly against CSV, JSON, and JSON Lines objects in object storage. This quickstart walks through a typical workflow and shows how to get started quickly.

First-time workspace setup

  • Install the Python package and utilities.
  • Save your subscription credentials.
  • Link your storage account using the API.

Development workflow

  • Before querying a blob for the first time, call the API to prepare metadata for fast queries.
  • Run a query on the blob using the Python client.

1. Pick a blob to query

Pick a CSV or JSON blob in your object storage account that you want to query. You need the object URL plus the account name and key. AirMettle Select runs in Azure East US 2 today, so a storage account in that region is a good place to start.

2. Install the Python package

Use the Python client in this quickstart and install httpx for API calls.

pip install pyamselect httpx

3. Save your credentials

Add your subscription ID, API key, and storage account key as environment variables so credentials stay out of source code.

Linux / macOS / WSL / Git Bash
export AIRMETTLE_SUBSCRIPTION_ID="YOUR_SUBSCRIPTION_ID"
export AIRMETTLE_API_KEY="YOUR_API_KEY"
export STORAGE_ACCOUNT_KEY="YOUR_STORAGE_ACCOUNT_KEY"
PowerShell
$env:AIRMETTLE_SUBSCRIPTION_ID="YOUR_SUBSCRIPTION_ID"
$env:AIRMETTLE_API_KEY="YOUR_API_KEY"
$env:STORAGE_ACCOUNT_KEY="YOUR_STORAGE_ACCOUNT_KEY"
Command Prompt
set AIRMETTLE_SUBSCRIPTION_ID=YOUR_SUBSCRIPTION_ID
set AIRMETTLE_API_KEY=YOUR_API_KEY
set STORAGE_ACCOUNT_KEY=YOUR_STORAGE_ACCOUNT_KEY

4. Link your storage account using the API

Link your object storage account to AirMettle Select. This is a one-time step per account.

import os
import httpx

# Include your subscription credentials in the request headers
headers = {
    "x-subscription-id": os.getenv("AIRMETTLE_SUBSCRIPTION_ID"),
    "x-api-key": os.getenv("AIRMETTLE_API_KEY"),
}

# Create the request body with the storage account name and key
request = {
    "storage_account": "yourstorageaccount",
    "account_key": os.getenv("STORAGE_ACCOUNT_KEY")
}

response = httpx.post("https://api.airmettle.com/api/v1/buckets", json=request, headers=headers)
print(response.status_code, response.text)

A 201 Created response means the account was linked successfully.

5. Create metadata for the blob using the API

Before querying a blob, AirMettle Select generates a small sidecar metadata file. These sidecars live in a hidden directory alongside your data and enable parallel high-performance reads.

You can generate a sidecar on demand. The original blob is never modified, and you can delete and regenerate the sidecar at any time.

import os
import httpx

# Specify the blob URL and your subscription credentials in the request body
request = {
    "subscription_id": os.getenv("AIRMETTLE_SUBSCRIPTION_ID"),
    "api_key": os.getenv("AIRMETTLE_API_KEY"),
    "blob_url": "https://yourstore.blob.core.windows.net/container/yourblob.csv",
    "account_key": os.getenv("STORAGE_ACCOUNT_KEY")
}

response = httpx.post("https://api.airmettle.com/v1/prepare", json=request)
print(response.status_code, response.text)

A 200 OK response means the metadata object is ready and queryable. A 202 Accepted response means generation is asynchronous and includes a status_url for polling.

Status values:
ready means the sidecar is available.
pending means generation is still in progress.
failed means metadata generation failed; review error details in the response body.

6. Run a query

In step 5, you prepared a blob using its full blob_url. In this step, identify the same blob by storage_account, container, and blob. The response is a stream of selected rows in the requested format.

import os
from pyamselect import AMSelectClient, SelectRequest, CSVInputOptions, CSVOutputOptions

# Specify which blob to query, the SQL, and input/output options
request = SelectRequest(
    subscription_id=os.getenv("AIRMETTLE_SUBSCRIPTION_ID"),
    api_key=os.getenv("AIRMETTLE_API_KEY"),
    storage_account="yourstorageaccount",
    container="yourcontainer",
    blob="yourblob.csv",
    expression="SELECT * FROM s3object", # Your SQL query
    input_options=CSVInputOptions(csv_header_config="use",csv_field_delimiter=","), # input as CSV
    output_options=CSVOutputOptions(), # output as CSV
)

# Create the client to connect to AirMettle Select
with AMSelectClient("api.airmettle.com/query", 8443) as client:

    # Run the query and collect the results as a string
    result = client.select_to_string(request)
    print(result)

    # Alternatively, write results directly to a file
    # client.select_to_file(request, "output.csv")

    # Or write results to a binary stream, such as a BytesIO object
    # client.select_to_stream(request, stream)
Next step

Start by linking one storage account, prepare metadata for a few sample blobs, and run your first query.

Request quickstart help ↗
File formats

File formats for AirMettle Select.

AirMettle Select runs SQL directly against CSV, JSON, and JSON Lines objects, including GZIP-compressed inputs. Contact us to evaluate Parquet and scientific formats through early access.

Currently supported
Format
Description
Notes
Format{{ f.name }}
Description{{ f.description }}
Notes{{ f.notes }}
Early access
{{ f.name }}

{{ f.description }}

Input and output options

Choose how data is parsed and returned.

When creating a request, set input options for parsing and output options for the stream format returned to your application.

  • CSV input options include header handling and delimiter controls.
  • Equivalent JSON options apply to JSON and NDJSON objects.
  • CSV output options return selected rows in CSV stream form.
from pyamselect import SelectRequest, CSVInputOptions, CSVOutputOptions

request = SelectRequest(
    ...
    expression="SELECT * FROM s3object",
    input_options=CSVInputOptions(
        csv_header_config="use",
        csv_field_delimiter=","
    ),
    output_options=CSVOutputOptions(),
)
Prepare and query workflow

Same three-step path for every supported format.

  1. Link the storage account once.
  2. Call prepare on the blob URL to generate sidecar metadata.
  3. Issue the SQL query with storage account, container, and blob.
Unsupported types return a clear prepare error response.
SQL support

Familiar SQL support for object storage queries.

AirMettle Select runs familiar SQL against CSV and JSON objects in object storage. Built on the same SQL surface as Amazon S3 Select, it provides a fast way to filter, project, and aggregate data in place.

Sidecar metadata is generated once per blob so subsequent queries run in parallel and return results quickly.

Supported data types
Type
Description
Example
Type{{ t.type }}
Description{{ t.description }}
Example{{ t.example }}
Built-in functions
Conversion
CAST(expr AS type)
Temporal
{{ f }}
Pattern matching
regexp_contains(string, pattern)
Aggregate functions

Aggregate functions ignore MISSING values and return a single summary row.

Function
Description
Function{{ f.fn }}
Description{{ f.description }}
Supported query structure

AirMettle Select implements a focused SQL subset optimized for object storage. The core statement structure is shown below. Currently, explicit JOINs are not supported.

SELECT [projections]
FROM [relation]
WHERE [condition]
LIMIT [number]
SELECT list

Project specific columns, expressions, or function results and use aliases with AS.

SELECT column1, column2
SELECT *
FROM clause

Query a single object relation.

FROM S3Object
WHERE clause

Filter rows with boolean expressions.

WHERE amount > 100
WHERE status = 'active' AND region IS NOT MISSING
WHERE regexp_contains(email, '@company\\.com')
LIMIT clause

Cap returned records for sampling and preview.

LIMIT 100
Working with CSV

Reference CSV columns by position (_1, _2, and so on) or by header name when headers are present. Header names are case-insensitive unless wrapped in double quotes.

SELECT _1, _3 FROM S3Object WHERE _2 > 50
SELECT email FROM S3Object WHERE status = 'active'
JSON notation and identifiers

Use dot notation for nested fields and zero-based indexes for arrays. Start from S3Object[*] when JSON is treated as an array of root values.

SELECT s.projects[0].project_name FROM S3Object s
SELECT s."CAST", s."Name" FROM S3Object s
Why AirMettle Select
Familiar SQL syntax for filtering, projection, and aggregation.
No data movement required before querying.
Parallel execution enabled by sidecar metadata.
S3 Select compatible surface with minor query adjustments.
Use cases

Four use cases.
One direct data path.

Start with the storage and query benefits of compressed logs, then see that same direct data path applied to operational analytics, standardized performance, and Microsoft Fabric.

Operational event streams

Investigate recent events without loading a warehouse.

GH Archive publishes GitHub activity as native hourly GZIP-compressed JSON Lines objects. This public example compares a newly arrived one-hour object with a six-hour operational window.

Prepare each object once, then query it in place—without a conversion pipeline, a warehouse load, or a query cluster kept warm for sporadic investigations.

{{ f.label }} {{ f.value }} {{ f.linkLabel }}
Choose the operational window

{{ operationalWindowTitle }}

{{ operationalWindowDescription }}

The same ten operational checks run against one native object or six consecutive hourly objects.

Selected source: {{ operationalWindowFiles }} {{ operationalWindowObjectCount }} · {{ operationalWindowSize }} compressed
Operational question
AirMettle Select
Serverless reference
Relative
Operational question {{ q.kind }} {{ q.title }} {{ q.job }} Benchmark status · {{ q.resultLabel }}
View SQL
{{ q.sql }}
AirMettle Select{{ q.airmettleRuntime }}
Serverless reference{{ q.referenceRuntime }}
Relative{{ q.relative }}
Review exact public source files

AirMettle Select and serverless reference timings were measured on these exact public files using equivalent queries. Preparation is excluded from query runtime.

Skip format conversionQuery the native JSON Lines GZIP objects your landing process already writes.
Avoid idle infrastructureDo not keep a separate query cluster warm for occasional checks and investigations.
Return only what mattersOnly the focused result continues to an analyst, application, alert, or downstream workflow.
Analytical performance benchmark

AirMettle Select on ClickBench.

See the measured advantage on CSV and JSON side by side. Both comparisons use the same 42 valid ClickBench queries and aligned serverless-reference results.

CB

ClickBench results are on the way.

AirMettle Select and serverless reference measurements will be published side by side with the workload and test details.

AirMettle Select Serverless reference Same 42 valid queries · shared log scale · lower is better
ClickBench source format

{{ v.format }}

{{ v.dataSize }} queried
{{ v.suiteSpeedup }} faster across the full suite
Queries faster{{ v.fasterQueries }}
Relative runtime{{ v.relativeRuntime }}
Median query{{ v.medianSpeedup }}
Runtime by query · logarithmic scale
{{ p.synapseLabel }} {{ p.selectLabel }}
42 queries in source order

Data sizes are calculated from the benchmark workbook's recorded dataset sizes and proportions. Each panel compares aligned AirMettle Select and mainstream serverless object-query results for the same valid ClickBench queries.

Maximize Performance. Minimal metadata overhead.

Keep logs compressed to save on both storage AND query costs.

Including metadata (kept in your buckets), total cost is typically 75% to 90%+ cheaper with GZIP than using raw data.

Query GZIP-compressed logs directly.

Run low-latency queries on existing GZIP-compressed CSV and JSON logs—without converting them to Parquet. Measured results on real log datasets show that GZIP query response times are competitive with those on the corresponding uncompressed originals.

<0.1% Raw metadata overhead across all four measured datasets
≤0.5% GZIP metadata compared with the original uncompressed data
75–90%+ Less total storage after adding metadata to GZIP objects
{{ d.name }} {{ d.scope }}
{{ d.sourceLabel }} ↗
RAW · PREPARED {{ d.rawTotal }} total prepared storage
Data{{ d.rawObject }}
Metadata{{ d.rawMetadata }}
Metadata / data{{ d.rawMetadataPercent }}
GZIP · PREPARED {{ d.gzipTotal }} total prepared storage
Data{{ d.gzipObject }}
Metadata{{ d.gzipMetadata }}
Metadata / data{{ d.gzipMetadataPercent }}
RAW PREPARED · {{ d.rawTotal }} GZIP PREPARED · {{ d.gzipTotal }}
Total prepared storage{{ d.rawTotal }} Raw → {{ d.gzipTotal }} GZIP {{ d.storageSaved }}SMALLER THAN RAW

Bars compare complete prepared footprints. Storage savings use GZIP object plus Select metadata versus the corresponding original Raw object. Values were measured on the linked public datasets.

Query performance

Faster Response Time,
Lower cost for storage AND queries

{{ compressionViewDescription }}

Dataset
Query
{{ compressionMetricAHeader }}
{{ compressionMetricBHeader }}
Relative
Dataset{{ b.dataset }}
Query
{{ q.query }} {{ q.matchingRowsLabel }} matching rows
View SQL
{{ q.sql }}
{{ compressionMetricAHeader }}
{{ q.metricA }}
{{ compressionMetricBHeader }}
{{ q.metricB }}
Relative
{{ q.relative }}{{ q.relativeNote }}

{{ compressionViewMethodology }}

Preparation pricing

Prepare once.
Typically no extra charge.

Each source object is prepared only once.

Included with query usage No separate preparation charge When monthly query volume meets or exceeds newly prepared data volume.
Only the difference Uncovered preparation volume only If preparation exceeds query volume that month, only the uncovered amount is billed at the standard $5/TB rate.
Query usage · $5/TB scanned, billed monthly
AirMettle Select inside Microsoft Fabric

Filter first.
Let Fabric do more with less.

Use AirMettle Select as a query step inside Fabric pipelines and notebooks. It filters large source objects in place and returns only the selected rows, so Fabric can transform, enrich, model, and report on a much smaller input.

01 · Fabric orchestrates Start the query A pipeline or notebook submits the SQL selection through the REST API.
02 · AirMettle Select Filter in place Query prepared Raw or compressed source objects in parallel where they already live.
03 · Focused result Return selected rows Send matching CSV or JSON rows back—not the complete source archive.
04 · Microsoft Fabric Complete the workflow Transform, enrich, model, or report on the smaller result inside Fabric.
Example · operational analytics

Keep the archive. Bring only the incident slice into Fabric.

An operations team keeps compressed audit logs in object storage. A Fabric pipeline calls AirMettle Select for the high-risk changes in an investigation window. Only that focused result enters Fabric for enrichment, modeling, or reporting; the complete archive stays in customer storage.

Keep the archiveOriginal objects remain in customer storage.
Select before loadingOnly relevant rows enter the Fabric workflow.
Continue in FabricTransform, model, or report on the focused result.
Bring your own query

See how AirMettle Select performs on your data.

Try it on Azure ↗
AirMettle Select MCP

Ask your data in plain English.

The AirMettle Select MCP server lets AI assistants query the files in your object storage. You ask a question, the assistant writes the SQL, and AirMettle Select runs it where the data already lives. Compact answers come back to your chat, and your data stays in your storage account.

MCP (Model Context Protocol) is the open standard AI tools use to connect to outside tools and data. One small package, amselect-mcp, runs on your machine and works with any MCP-capable assistant, whichever model it uses.

Watch it work

Two demos, each in two views.

The standard view is the chat you would see yourself. The detailed view shows every tool call: the exact SQL the AI wrote and the rows AirMettle Select returned. Jump straight to any question.

{{ d.k }}

{{ d.t }}

{{ d.d }}

Jump to a question
QQuestionWatchDetailed
{{ q.n }} {{ q.q }} {{ q.at }} {{ q.detailAt }}
About the demo setup

Both demos run through the Grok CLI on public data: SSB at scale factor 10 (CSV, GZIP CSV, and Parquet) and ClickBench hits — 99,997,497 rows in a 14.8 GB Parquet file. Tests ran on a smaller cluster than the live service uses, with the autoscaling we use to keep latency low turned off, so these times are conservative relative to production. On that setup, most calls returned in under a second; a full scan of the 60-million-row lineorder.parquet took about 4 seconds. Parquet is available by request for early access.

Every SQL call, with its timestamp

Each row is one call the AI made: when it happens in the video, the question it served, the file, and the exact SQL. Click a time to jump straight to that moment. The standard view keeps the SQL off screen, so its SQL comes from the session log.

{{ c.title }}{{ c.sub }} {{ c.count }}
Time
Q
File
SQL
Time in the video{{ r.time }}
Question{{ r.q }}
File{{ r.file }}
SQL{{ r.sql }}
How it works

Your AI tool, your machine, your storage.

The user asks in plain English. The AI tool talks to amselect-mcp on the user's machine over MCP, amselect-mcp calls AirMettle Select over HTTPS, and AirMettle Select scans the object store in place and returns rows or aggregates only. MCP over stdio pyamselect, HTTPS scans in place rows or aggregates only User asks in plain English AI tool amselect-mcp AirMettle Select Your object store Claude Code, Grok CLI, Cursor… on your machine next to your data today: Azure Blob Storage CSV, JSON lines, Parquet

Your AI tool starts amselect-mcp as a local helper process and talks to it over standard input and output. Each question becomes one or more SQL calls that AirMettle Select runs next to the data in your object store.

{{ n.k }}

{{ n.d }}

Your AI tool sees three tools. When it connects, the server also gives it a short guide to the SQL dialect and the prepare-then-query workflow, so a general-purpose assistant prepares a new file on its own and keeps its queries focused.

Tool
What it does
When the AI uses it
{{ t.name }}
{{ t.what }}
{{ t.when }}
Works with MCP-capable AI tools, including
{{ c.name }}
Setup

Connect your AI tool in a few minutes.

Your AI tool starts amselect-mcp on demand. All you need is an AirMettle Select subscription from Azure Marketplace. AirMettle Select runs in Azure East US 2 today, with more regions on the way.

1. Get the package

Run it with uv, which fetches it from PyPI on demand, or install it with pip (Python 3.10 or later). With pip, use amselect-mcp wherever this page says uvx amselect-mcp.

With uv (recommended)
uvx amselect-mcp
With pip
pip install amselect-mcp

2. Have your AirMettle Select details ready

Four values from your subscription reach amselect-mcp as environment variables.

VariableValue
AMSELECT_HOSTQuery endpoint host
AMSELECT_SUBSCRIPTION_IDSubscription ID
AMSELECT_API_KEYSubscription API key
AMSELECT_METADATA_ENDPOINTMetadata service URL, used to prepare new files

3. Register it with your AI tool

Save the values in your tool's configuration, so the server works from any terminal and in desktop apps.

Claude Code
claude mcp add amselect \
    -e AMSELECT_HOST="<query-host>" \
    -e AMSELECT_METADATA_ENDPOINT="https://<metadata-endpoint>" \
    -e AMSELECT_SUBSCRIPTION_ID="<subscription-id>" \
    -e AMSELECT_API_KEY="<api-key>" \
    -- uvx amselect-mcp
Grok CLI
grok mcp add amselect \
    -e AMSELECT_HOST="<query-host>" \
    -e AMSELECT_METADATA_ENDPOINT="https://<metadata-endpoint>" \
    -e AMSELECT_SUBSCRIPTION_ID="<subscription-id>" \
    -e AMSELECT_API_KEY="<api-key>" \
    uvx amselect-mcp
Claude Desktop and Cursor
{
  "mcpServers": {
    "amselect": {
      "command": "uvx",
      "args": ["amselect-mcp"],
      "env": {
        "AMSELECT_HOST": "<query-host>",
        "AMSELECT_METADATA_ENDPOINT": "https://<metadata-endpoint>",
        "AMSELECT_SUBSCRIPTION_ID": "<subscription-id>",
        "AMSELECT_API_KEY": "<api-key>"
      }
    }
  }
}

Add it to claude_desktop_config.json (Claude Desktop: Settings → Developer → Edit Config) or ~/.cursor/mcp.json, then restart the app.

VS Code
{
  "inputs": [{
    "type": "promptString",
    "id": "amselect-api-key",
    "description": "AirMettle Select API key",
    "password": true
  }],
  "servers": {
    "amselect": {
      "type": "stdio",
      "command": "uvx",
      "args": ["amselect-mcp"],
      "env": {
        "AMSELECT_HOST": "<query-host>",
        "AMSELECT_METADATA_ENDPOINT": "https://<metadata-endpoint>",
        "AMSELECT_SUBSCRIPTION_ID": "<subscription-id>",
        "AMSELECT_API_KEY": "${input:amselect-api-key}"
      }
    }
  }
}

Add it to .vscode/mcp.json. VS Code asks for the API key the first time the server starts and keeps it in its secret storage.

Codex CLI, Gemini CLI and any other MCP-capable tool: register the command uvx amselect-mcp with the four values above. Keep the API key out of shared or committed files.

Built for compact answers

Small results for the model, full results when you want them.

{{ p.t }}

{{ p.d }}

Bring your own questions

Ask your own data in plain English.

Try it on Azure ↗
Security and trust

Designed around the data boundary you already trust.

Keep source data in object storage and limit each query to the storage scope your application is allowed to use.

{{ s.icon }}

{{ s.t }}

{{ s.d }}

FAQ

Questions, answered.

The essentials for evaluating AirMettle Select, from supported data to deployment and pricing.

{{ f.a }} {{ f.ctaLabel }}
Early access

Contact us for {{ contactInterest }}.

If your email application does not open automatically, please contact us at the address below.

Email{{ contactEmail }}
{{ contactCopyStatus }}