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

# Data Model

> Reference for core tables written by Steward and queried by the dashboard.

This page documents the columns you’ll see when querying usage directly. Steward writes locally first and batches metadata to Butler; the dashboard reads from Butler’s database.

<Info>
  <strong>Where data lives</strong>

  * Steward (gateway) writes request rows immediately to its local DB and uploads bodies to your S3/GCS when configured.
  * Butler (control plane) ingests usage/metadata in batches from Steward and serves the dashboard/API.
  * The Web dashboard queries Butler. If you query directly, prefer Butler’s DB for analytics consistency.
</Info>

## llm\_requests

One row per proxied request.

| Column                   | Type            | Description                                                                                            |
| ------------------------ | --------------- | ------------------------------------------------------------------------------------------------------ |
| `id`                     | `uuid`          | Request id.                                                                                            |
| `majordomo_api_key_id`   | `uuid`          | Owning Majordomo API key.                                                                              |
| `provider_api_key_hash`  | `varchar(64)`   | Hash of upstream provider Authorization header.                                                        |
| `provider_api_key_alias` | `varchar(255)`  | Optional alias from `X-Majordomo-Provider-Alias`.                                                      |
| `provider`               | `varchar(100)`  | `openai`, `anthropic`, `gemini`, `bedrock`, `fireworks`, `together`, or `deepseek`.                    |
| `model`                  | `varchar(100)`  | Model name as reported (or translated).                                                                |
| `request_path`           | `text`          | Upstream path (e.g., `/v1/chat/completions`).                                                          |
| `request_method`         | `text`          | HTTP method.                                                                                           |
| `requested_at`           | `timestamptz`   | Timestamp when request was received.                                                                   |
| `responded_at`           | `timestamptz`   | Timestamp when response was fully sent.                                                                |
| `response_time_ms`       | `int`           | Wall-clock response time.                                                                              |
| `input_tokens`           | `int`           | Count parsed from provider response.                                                                   |
| `output_tokens`          | `int`           | Count parsed from provider response.                                                                   |
| `cached_tokens`          | `int`           | Prompt caching read tokens (if applicable).                                                            |
| `cache_creation_tokens`  | `int`           | Tokens charged to create cache entries.                                                                |
| `input_cost`             | `numeric(12,8)` | Calculated cost for input tokens.                                                                      |
| `output_cost`            | `numeric(12,8)` | Calculated cost for output tokens.                                                                     |
| `total_cost`             | `numeric(12,8)` | Sum of input/output (and cache) costs.                                                                 |
| `status_code`            | `int`           | Upstream HTTP status.                                                                                  |
| `error_message`          | `text`          | Truncated error body when status ≥ 400.                                                                |
| `raw_metadata`           | `jsonb`         | All custom headers (`X-Majordomo-*`, minus reserved) without indexing.                                 |
| `indexed_metadata`       | `jsonb`         | Subset of active keys copied for fast `@>` queries (GIN index).                                        |
| `request_body`           | `text`          | Optional local body copy when Postgres body storage is enabled.                                        |
| `response_body`          | `text`          | Optional local body copy when Postgres body storage is enabled.                                        |
| `body_s3_key`            | `text`          | Object key when uploaded to S3/GCS via personal/org config.                                            |
| `model_alias_found`      | `bool`          | True if pricing alias resolved for the model.                                                          |
| `org_id`                 | `uuid`          | Owning org (shadow for filtering/joins).                                                               |
| `created_at`             | `timestamptz`   | Row creation timestamp.                                                                                |
| `synced_to_butler`       | `bool`          | Steward-only: batched to Butler yet.                                                                   |
| `trace_id`               | `text`          | [Agent run](/guides/agent-runs) id from `X-Majordomo-Trace-Id`. `NULL` for standalone requests.        |
| `span_path`              | `text`          | Canonical `/`-joined ancestor step names from `X-Majordomo-Span-Path` (e.g. `planner/tool:search_db`). |
| `span_name`              | `text`          | Label for this call in the waterfall (`X-Majordomo-Span-Name`, defaults to the model).                 |
| `span_id`                | `uuid`          | This call's span id (defaults to the request id).                                                      |
| `parent_span_id`         | `uuid`          | Deterministic id of the interior step named by `span_path`, derived from `(trace_id, span_path)`.      |

Indexes: by `(majordomo_api_key_id, requested_at DESC)`, a GIN index on `indexed_metadata`, and a partial index on `trace_id` (where not null) for run lookups.

## llm\_requests\_metadata\_keys

Per-API-key registry of discovered metadata keys and their indexing state.

| Column                 | Type           | Description                                                  |
| ---------------------- | -------------- | ------------------------------------------------------------ |
| `majordomo_api_key_id` | `uuid`         | API key owner. Part of PK.                                   |
| `key_name`             | `varchar(255)` | Stored name (prefix `X-Majordomo-` is stripped). Part of PK. |
| `display_name`         | `varchar(255)` | UI label.                                                    |
| `key_type`             | `varchar(50)`  | Semantic hint, default `string`.                             |
| `is_required`          | `bool`         | Reserved for future validation.                              |
| `is_active`            | `bool`         | If true, key is copied into `indexed_metadata`.              |
| `activated_at`         | `timestamptz`  | When indexing was enabled.                                   |
| `request_count`        | `bigint`       | How many requests carried this key.                          |
| `last_seen_at`         | `timestamptz`  | Most recent occurrence.                                      |
| `hll_state`            | `bytea`        | HyperLogLog state.                                           |
| `approx_cardinality`   | `int`          | Approx unique values for the key.                            |
| `hll_updated_at`       | `timestamptz`  | Last HLL update.                                             |
| `created_at`           | `timestamptz`  | Row creation timestamp.                                      |

Index: `is_active` per API key for fast lookups.

## Notes

* Reserved headers that do not enter `raw_metadata`: `X-Majordomo-Key`, `X-Majordomo-Provider`, `X-Majordomo-Provider-Alias`, `X-Majordomo-Client`, `X-Majordomo-Trace-Id`, `X-Majordomo-Span-Path`, `X-Majordomo-Span-Name`.
* Bodies in Postgres are off by default; prefer S3/GCS via [Cloud Body Storage](/configuration/cloud-storage).

***

## SQL primer

For end‑to‑end examples, see [Cost Attribution](/guides/cost-attribution). A few quick patterns:

```sql theme={null}
-- Last 7 days by day
SELECT date_trunc('day', requested_at) AS day,
       COUNT(*) AS requests,
       SUM(total_cost) AS total_cost
FROM llm_requests
WHERE requested_at >= now() - interval '7 days'
GROUP BY 1
ORDER BY 1;
```

```sql theme={null}
-- Filter by an indexed metadata key (fast)
SELECT COUNT(*), SUM(total_cost)
FROM llm_requests
WHERE indexed_metadata @> '{"Feature": "document-review"}';
```

```sql theme={null}
-- Filter by a non‑indexed key (works, slower)
SELECT COUNT(*), SUM(total_cost)
FROM llm_requests
WHERE raw_metadata->>'Team' = 'platform';
```
