Skip to main content

Per-query cost guard for cloud databases. Set dollar or byte limits before any query runs.

Project description

query-cost-guard

query-cost-guard

Per-query cost guard for BigQuery. Set dollar or byte limits before any query runs.

Why

BigQuery charges per byte scanned. A single bad query can burn through your daily quota. The native maximum_bytes_billed only speaks in bytes — this package lets you think in dollars.

Install

pip install query-cost-guard

# With CLI
pip install query-cost-guard[cli]

Usage

Dollar-based guard

from google.cloud.bigquery import Client
from query_cost_guard import QueryCostGuard, QueryParams

guard = QueryCostGuard(client=Client())

result = guard.query(
    sql="SELECT * FROM `project.dataset.table` WHERE date > '2026-01-01'",
    params=QueryParams(max_cost_usd=0.50),
)

result.rows              # list[dict]
result.actual_cost_usd   # 0.03
result.bytes_billed      # 4_831_838_208
result.duration_seconds  # 2.41

Byte-based guard

result = guard.query(
    sql="SELECT * FROM `project.dataset.table`",
    params=QueryParams(max_bytes=5 * 1024**4),  # 5 TiB
)

max_cost_usd and max_bytes are mutually exclusive.

When cost exceeds the limit

BigQuery rejects the query before execution — no bytes are billed.

from query_cost_guard import QueryCostExceededError, QueryParams

try:
    result = guard.query(sql=huge_query, params=QueryParams(max_cost_usd=0.10))
except QueryCostExceededError as e:
    e.context.estimated_cost_usd  # 2.34
    e.context.max_cost_usd        # 0.10
    e.context.bytes_estimated     # 374_000_000_000

With existing job config

from google.cloud.bigquery import QueryJobConfig, ScalarQueryParameter

result = guard.query(
    sql=sql,
    params=QueryParams(max_cost_usd=1.00, query_tag="observation_troubleshooting"),
    job_config=QueryJobConfig(
        query_parameters=[ScalarQueryParameter("account_id", "INT64", 115)]
    ),
    location="US",
)

Pricing

Live pricing is fetched from the Cloud Billing Catalog API and cached for 24 hours. If the API is unavailable, falls back to the static rate of $6.25/TiB.

from query_cost_guard import QueryCostGuard, OnPricingFailure

# Fail hard if pricing can't be resolved
guard = QueryCostGuard(client=client, on_pricing_failure=OnPricingFailure.RAISE)

# Or pin a known price
guard = QueryCostGuard(client=client, price_per_tib_override=6.25)

Dry-run estimation

estimate = guard.estimate(sql="SELECT * FROM `project.dataset.big_table`")
estimate.estimated_bytes       # 4_831_838_208
estimate.estimated_cost_usd    # 0.0275
estimate.price_per_tib_usd     # 6.25

CLI

Estimate query cost without executing:

query-cost-guard --project my-gcp-project estimate \
  --query "SELECT * FROM \`project.dataset.table\`"

# Estimated bytes:  4,831,838,208
# Estimated cost:   $0.0275 (at $6.25/TiB)

With a cost threshold:

query-cost-guard --project my-gcp-project estimate \
  --query "SELECT * FROM big_table" \
  --max-cost 0.50

# Guard:  ✓ PASS (limit $0.50)

JSON output, file input, stdin:

query-cost-guard --project my-proj estimate --query "SELECT 1" --json
query-cost-guard --project my-proj estimate --file query.sql
cat query.sql | query-cost-guard --project my-proj estimate

Credentials default to Application Default Credentials. Override with --credentials /path/to/sa.json.

How it works

Uses BigQuery's maximum_bytes_billed on the QueryJobConfig. Single API call, no race condition, enforced server-side. Both estimate() and the CLI use dry_run=True for zero-cost estimation.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

query_cost_guard-0.1.1.tar.gz (1.0 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

query_cost_guard-0.1.1-py3-none-any.whl (10.7 kB view details)

Uploaded Python 3

File details

Details for the file query_cost_guard-0.1.1.tar.gz.

File metadata

  • Download URL: query_cost_guard-0.1.1.tar.gz
  • Upload date:
  • Size: 1.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for query_cost_guard-0.1.1.tar.gz
Algorithm Hash digest
SHA256 898422a9977e13d46621a55689689b6523605d47aae9bf23b6e192e99fd9e477
MD5 767956f5e0f020323aea8d4f1300fbc2
BLAKE2b-256 5ed87a7da68d295ec0eb7b0e2e7f25833c013f91cc17edfe7be92298d6e453cf

See more details on using hashes here.

Provenance

The following attestation bundles were made for query_cost_guard-0.1.1.tar.gz:

Publisher: release.yml on yaelmi3/query-cost-guard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file query_cost_guard-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for query_cost_guard-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a2a32653f19819acbc4c6b6acf13e165ec262be98c51407069ed6afc9c76756b
MD5 132af4777f6d4f6c82ae3efe5d36ed52
BLAKE2b-256 5c5efcb1895f8f7fa8c7c00b3d5338787fe675e500099ba01bdd6259eb37b745

See more details on using hashes here.

Provenance

The following attestation bundles were made for query_cost_guard-0.1.1-py3-none-any.whl:

Publisher: release.yml on yaelmi3/query-cost-guard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page