# Monitoring usage and costs
> Track compute and storage usage in MotherDuck using SQL views, understand how usage maps to your bill, and find ways to optimize costs.
MotherDuck provides SQL views and a billing dashboard to help you understand your compute and storage consumption. This guide shows how to query your usage data, interpret the results in the context of your bill, and identify opportunities to reduce costs.

A **Compute Unit (CU)** is the amount of CPU and memory usage over time; compute is metered in CU hours. See the [pricing model](/about-motherduck/billing/pricing/) for how CU hours map to charges.

## Tracking compute usage

:::info
The `QUERY_HISTORY` view is available on Business plans and requires organization admin access. The editable examples on this page show sample results; select **Run** to query your own organization's data.
:::

The [`MD_INFORMATION_SCHEMA.QUERY_HISTORY`](/sql-reference/motherduck-sql-reference/md_information_schema/query_history/) view records every query run across your organization. Use it to understand which users, queries, and duckling types are driving compute consumption.

For a visual overview, organization admins can also use the [Duckling overview](/getting-started/interfaces/motherduck-quick-tour/#duckling-overview) page (**Settings** → **Duckling overview**) to see active minutes, query volume, spills, and errors per Duckling over the last 24 hours.

![Duckling overview page listing each Duckling with its account, size, active minutes, query volume, activity sparkline, wait time, spills, and errors](img/duckling-overview.png)

### Compute hours by duckling type

Summarize execution hours per duckling type over a given period. The example results below show what the output looks like; run the query to see your own organization's data.

#### Compute hours by duckling type

Database: `my_db`

```sql
SELECT
    instance_type,
    COUNT(*) AS query_count,
    ROUND(SUM(EPOCH(execution_time)) / 3600, 2) AS execution_hours
FROM md_information_schema.query_history
WHERE start_time >= CURRENT_DATE - INTERVAL 30 DAYS
GROUP BY instance_type
ORDER BY execution_hours DESC;
```

:::note
Execution hours from `QUERY_HISTORY` approximate your billed compute but don't match it exactly. Standard and larger Ducklings are billed for wall-clock time, including startup and the [cooldown period](/about-motherduck/billing/pricing/#compute-pricing) after the last query. Pulse Ducklings are metered per query on CUs consumed.
:::

### Identify expensive queries

Find the longest-running queries to spot optimization opportunities. The `spilled_gb` column shows how much data each query [spilled to disk](https://duckdb.org/docs/stable/guides/performance/how_to_tune_workloads.html#spilling-to-disk) because it did not fit in memory: queries that spill run slower and cost more, and are a sign the workload needs a larger [Duckling size](/about-motherduck/billing/duckling-sizes/).

#### Longest-running queries in the past 7 days

Database: `my_db`

```sql
SELECT
    query_id,
    user_name,
    instance_type,
    execution_time,
    total_elapsed_time,
    ROUND(bytes_spilled_to_disk / 1e9, 2) AS spilled_gb,
    LEFT(query_text, 200) AS query_preview
FROM md_information_schema.query_history
WHERE start_time >= CURRENT_DATE - INTERVAL 7 DAYS
ORDER BY execution_time DESC
LIMIT 20;
```

### Usage by user

Break down compute consumption per user to understand who is driving costs:

#### Compute usage by user

Database: `my_db`

```sql
SELECT
    user_name,
    instance_type,
    COUNT(*) AS query_count,
    ROUND(SUM(EPOCH(execution_time)) / 3600, 2) AS execution_hours
FROM md_information_schema.query_history
WHERE start_time >= CURRENT_DATE - INTERVAL 30 DAYS
GROUP BY user_name, instance_type
ORDER BY execution_hours DESC;
```

:::tip
To break usage down by pipeline, integration, or tenant rather than by user, set a custom user agent when connecting and group by the `user_agent` column. See [Tag workloads with custom user agents](/about-motherduck/billing/tag-workloads-with-custom-user-agents/).
:::

## Tracking storage usage

:::info
The `STORAGE_INFO` views require organization admin access.
:::

### Current storage by database

Use [`MD_INFORMATION_SCHEMA.STORAGE_INFO`](/sql-reference/motherduck-sql-reference/md_information_schema/storage_info/) to see storage across all databases:

#### Storage by database

Database: `my_db`

```sql
SELECT
    database_name,
    user_name,
    transient,
    ROUND(active_bytes / 1e9, 2) AS active_gb,
    ROUND(historical_bytes / 1e9, 2) AS historical_gb,
    ROUND(retained_for_clone_bytes / 1e9, 2) AS cloned_gb,
    ROUND(failsafe_bytes / 1e9, 2) AS failsafe_gb,
    ROUND((active_bytes + historical_bytes + retained_for_clone_bytes + failsafe_bytes) / 1e9, 2) AS total_gb
FROM md_information_schema.storage_info
ORDER BY total_gb DESC;
```

### Understanding storage byte types

Your storage bill includes several categories of bytes:

| Byte type | Description |
|-----------|-------------|
| `active_bytes` | Data referenced by the database: your live tables and indexes. |
| `historical_bytes` | Previous versions of data retained for [point-in-time restore](/concepts/data-recovery/). Controlled by `snapshot_retention_days`. |
| `retained_for_clone_bytes` | Bytes retained because another database (through zero-copy clone) still references them. |
| `failsafe_bytes` | Bytes kept for a minimum failsafe period after they are no longer referenced. |

All four categories count toward your storage bill. To reduce `historical_bytes`, you can lower the snapshot retention period on databases where long retention is not needed.

### Estimate monthly storage cost

Calculate an approximate monthly storage bill based on current usage (US East rates):

#### Estimated monthly storage cost

Database: `my_db`

```sql
SELECT
    ROUND(SUM(active_bytes + historical_bytes + retained_for_clone_bytes + failsafe_bytes) / 1e9, 2) AS total_gb,
    ROUND(SUM(active_bytes + historical_bytes + retained_for_clone_bytes + failsafe_bytes) / 1e9 * 0.04, 2) AS estimated_monthly_cost_usd
FROM md_information_schema.storage_info;
```

:::note
Storage is billed based on your **average daily usage** over the billing period, not a single point-in-time snapshot. Use [`STORAGE_INFO_HISTORY`](/sql-reference/motherduck-sql-reference/md_information_schema/storage_info/) for trend analysis over the past 30 days.
:::

You can also get a quick overview of database sizes using [`PRAGMA database_size`](/sql-reference/motherduck-sql-reference/md_information_schema/database_size/), though this does not break down storage by byte type.

## Understanding your bill

Your MotherDuck bill has three main components:

### Platform fee

- **Lite plan:** $0/month (includes 10 CU hours and 10 GB storage)
- **Business plan:** $250/month

### Compute charges

Compute is billed per CU hour for each duckling type. The CU hour rate varies by duckling size and region. See the [compute pricing table](/about-motherduck/billing/pricing/#compute-pricing) for current rates.

For example, if you consumed 50 CU hours on Standard in US East during a month:
50 hours x $2.40/hour = **$120.00**

### Storage charges

Storage is billed based on your average daily usage (in GB) over the billing period, multiplied by the per-GB rate. See the [storage pricing table](/about-motherduck/billing/pricing/#storage-pricing) for current rates.

For example, if your average storage over the month is 200 GB in US East:
200 GB x $0.04/GB = **$8.00**

You can view your current and past invoices on the [Billing page](https://app.motherduck.com/settings/billing) in the MotherDuck UI. Costs are broken down per user and per service account. See [Managing your bill](/about-motherduck/billing/managing-billing/) for details.

## Cost optimization tips

### Choose the right duckling size

- Use **Pulse** for small, bursty, read-heavy queries (ad-hoc analytics, data apps). Pulse bills per CU consumed, not wall-clock time, so short queries are very efficient.
- Use **Standard** or larger for sustained, compute-heavy workloads. Pulse can consume high volumes of CUs when scaling up for intensive queries.
- See [Duckling Sizes](/about-motherduck/billing/duckling-sizes/) for guidance on when to use each size.

### Reduce storage costs

- Use [`TRANSIENT` databases](/concepts/storage-lifecycle/#storage-management) for intermediate or reproducible data (for example, staging tables and job outputs). Transient databases retain only a 1-day failsafe minimum with no historical snapshots.
- Lower `snapshot_retention_days` on databases where you don't need long retention of historical snapshots. The default is 1 day on Lite and 7 days on Business (configurable up to 90 days).
- Shares and zero-copy clones (`CREATE DATABASE X FROM DATABASE Y`) do not incur additional storage. Only incremental changes to the cloned database add to storage.

### Write efficient queries

- Use `LIMIT` during data exploration to avoid scanning and returning more data than needed.
- Filter early with `WHERE` clauses to reduce the amount of data processed.
- Check `bytes_spilled_to_disk` in `QUERY_HISTORY`: if queries frequently spill to disk, consider a larger duckling size for faster execution. The [Duckling overview](/getting-started/interfaces/motherduck-quick-tour/#duckling-overview) page also flags Ducklings with spills.

### Plan resource usage

- Schedule heavy batch jobs during off-peak hours. While the per-hour cost is the same, this helps avoid resource contention with interactive users.
- Use [read scaling](/key-tasks/authenticating-and-connecting-to-motherduck/read-scaling/) (Business plan) to separate read-heavy workloads from write operations.

## See also

- [Understanding the pricing model](/about-motherduck/billing/pricing/)
- [Managing your bill](/about-motherduck/billing/managing-billing/)
- [Duckling sizes](/about-motherduck/billing/duckling-sizes/)
- [Optimizing query performance](/key-tasks/query-performance/)


---

## Docs feedback

MotherDuck accepts optional user-submitted feedback about this page at `GET https://motherduck.com/docs/api/feedback/agent`.
For agents and automated tools, feedback submission should be user-confirmed before sending.

URL-encode query parameter values and send a GET request:

```text
GET https://motherduck.com/docs/api/feedback/agent?page_path=%2Fabout-motherduck%2Fbilling%2Fmonitoring-usage%2F&page_title=Monitoring%20usage%20and%20costs&text=<url-encoded user feedback, max 2000 characters>
```

Optionally append `&source=<url-encoded interface identifier>` such as `claude.ai` or `chatgpt`.

`page_path` and `text` are required; `page_title` and `source` are optional. Responses: `200 {"feedback_id": "<uuid>"}`, `400` for malformed query parameters, and `429` when rate-limited.
