> ## Documentation Index
> Fetch the complete documentation index at: https://docs.molesignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Querying

> Run SQL, PromQL-compatible metric queries, streaming searches, and asynchronous jobs over organization streams.

MoleSignal exposes a single query endpoint backed by **DataFusion**. The endpoint supports full SQL
— including joins, CTEs, and window functions — or a **PromQL subset** for metrics, all against the
same store.

## The query endpoint

```http theme={null}
POST /api/v1/query
Authorization: Bearer <jwt>
Content-Type: application/json
```

### Request body

| Field        | Type    | Required | Notes                                                                                                               |
| ------------ | ------- | -------- | ------------------------------------------------------------------------------------------------------------------- |
| `org_id`     | string  | ✅        | Retained in the body for compatibility; the authenticated organization is authoritative.                            |
| `language`   | string  | ✅        | `sql` or `promql`.                                                                                                  |
| `statement`  | string  | ✅        | The query text.                                                                                                     |
| `time_range` | object  | ✅        | `{ "start": <microseconds>, "end": <microseconds> }` — microseconds since epoch.                                    |
| `stream`     | object  | —        | `{ "name": "app", "stream_type": "logs" }`; queryable signal types are `logs`, `metrics`, `traces`, and `profiles`. |
| `limit`      | integer | —        | Row cap.                                                                                                            |

### Response

The response carries `columns`, array-shaped `rows`, `scanned_rows`, and `took_ms`. Federated
responses may also carry federation metadata.

<Note>
  Send `Accept: application/x-ndjson` to stream objects row-by-row, followed by a `__meta__`
  record. Streaming bypasses the result cache.
</Note>

## SQL

```bash theme={null}
curl -X POST http://localhost:5080/api/v1/query \
  -H "authorization: Bearer $MS_JWT" \
  -H 'content-type: application/json' \
  -d "{\"org_id\":\"$MS_ORG\",\"language\":\"sql\",
       \"statement\":\"SELECT level, count(*) FROM app WHERE _timestamp > 0 GROUP BY level\",
       \"time_range\":{\"start\":0,\"end\":2000000000000000},
       \"stream\":{\"name\":\"app\",\"stream_type\":\"logs\"}}"
```

Because logs, metrics, and traces live in the same store, one query can **join across signals** —
for example, join error logs to matching spans on `trace_id`:

```sql theme={null}
SELECT l.msg, t.duration_ms
FROM app AS l
JOIN spans AS t ON l.trace_id = t.trace_id
WHERE l.level = 'error'
```

## PromQL

Set `language: "promql"` to run PromQL over metric streams. Both instant and range queries are
supported (range steps through `[start, end]` and returns a matrix). Coverage is broad — the rate
family and all `*_over_time`, the standard aggregations (incl. `topk` / `limitk`),
`histogram_quantile`, `label_replace` / `label_join`, math & trig, the `and` / `or` / `unless` set
operators with `on` / `ignoring` + `group_left` / `group_right` matching, selector `@` / `offset`,
and subqueries.

```json theme={null}
{
  "org_id": "<org>",
  "language": "promql",
  "statement": "histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))",
  "time_range": { "start": 0, "end": 2000000000000000 }
}
```

<Card title="PromQL support matrix" icon="table-list" href="/en-US/query/promql-subset">
  The full list of supported functions, operators, and modifiers — plus the known gaps
  (native-histogram functions, the binary `default` fill-in).
</Card>

## Search around an event

To pull the N events immediately before and after a given one (log context view), use
`POST /api/v1/query/search_around` with `event_timestamp_us`, `stream`, `stream_type`, and optional
`before` / `after` counts (default 50 each).

## Async, inspection, and cancellation

* Add `Prefer: respond-async` to `POST /api/v1/query`, or submit directly to
  `POST /api/v1/query/jobs`, for a durable search job.
* `GET /api/v1/query/jobs/{id}` reports state; `/results` returns completed output.
* `POST /api/v1/query/inspect` plans without executing and returns query metadata and the available
  logical plan.
* `POST /api/v1/query/recommendations` analyzes a query profile without executing the query.
* `GET /api/v1/query/running` and `POST /api/v1/query/{id}/cancel` let organization administrators
  inspect and cancel active work.

Standard queries require `streams.query`. Active-query administration requires
`org.settings.read` or `org.settings.manage`.

## Federated search

Enterprise Edition can add `?clusters=local,cluster-name` to the query endpoint. Any non-local
target requires the `federated_search` entitlement. Unreachable remotes are represented as degraded
clusters in federation metadata instead of silently becoming local data.

## Caching

Queries flow through a 3-level cache — `file_meta`, `parquet_meta`, and `query_result` — plus a
parquet disk cache enabled by default (`./data/cache/parquet`, 10 GB LRU). Caching is transparent
to the response contract; use server metrics to measure cache behavior.
