FinOps ToolsΒΆ
Cost optimization and warehouse governance. These tools help you find where money is being wasted and fix it.
v0.7.3+ β warehouse parameter is now optional
Every finops_* tool used to require an explicit warehouse=<connection-name> argument. As of v0.7.3, the parameter is optional β if omitted, the tool auto-picks the first configured warehouse whose driver type supports the operation. Pass warehouse= explicitly when you have multiple compatible connections and want a specific one. The bare form (finops_query_history --days 7) works.
finops_query_historyΒΆ
Fetch recent query execution history from your warehouse.
> finops_query_history prod-snowflake --days 7
Recent Queries (top 10 by cost):
βββββ¬βββββββββββββββββββββββββββββββββββ¬βββββββββββ¬βββββββββ¬ββββββββββββ¬ββββββββββ
β # β Query (truncated) β Credits β Rows β Duration β Runs β
βββββΌβββββββββββββββββββββββββββββββββββΌβββββββββββΌβββββββββΌββββββββββββΌββββββββββ€
β 1 β SELECT * FROM events JOIN use... β 89.3 β 2.1B β 4m 12s β 47 β
β 2 β CREATE TABLE AS SELECT DISTIN... β 45.1 β 340M β 12m 33s β 1 β
β 3 β SELECT COUNT(DISTINCT user_id... β 23.7 β 890M β 1m 45s β 312 β
β 4 β INSERT INTO daily_agg SELECT... β 18.2 β 45M β 3m 21s β 7 β
β 5 β SELECT * FROM raw_clickstream...β 12.8 β 1.5B β 2m 08s β 3 β
βββββ΄βββββββββββββββββββββββββββββββββββ΄βββββββββββ΄βββββββββ΄ββββββββββββ΄ββββββββββ
Summary:
Total queries: 4,231
Total credits: 847.2
Avg credits/query: 0.20
Parameters:
- warehouse (optional, since v0.7.3): Connection name. If omitted, the first configured Snowflake / BigQuery / Databricks / PostgreSQL warehouse is auto-picked.
- days (optional, default: 7): Lookback period
- limit (optional, default: 100): Max queries returned
- user (optional): Filter by username
- warehouse_filter (optional, Snowflake-only): Filter the result rows by the in-warehouse compute name (different from the warehouse connection parameter). Use warehouse to pick which connection to query; use warehouse_filter to narrow which Snowflake virtual warehouse's queries appear in the output.
Data sources by warehouse:
- Snowflake: QUERY_HISTORY function
- BigQuery: region-qualified `region-<location>.INFORMATION_SCHEMA.JOBS` β the region is auto-resolved from the BigQuery connection's location (e.g. us, eu, us-central1, asia-northeast1). If location is unset the tool defaults to us. Set location explicitly for non-US projects or you will query the wrong region.
- Databricks: system.query.history
- PostgreSQL: pg_stat_statements
finops_analyze_creditsΒΆ
Break down credit consumption by warehouse, time, and user.
> finops_analyze_credits --days 30
# equivalent: finops_analyze_credits prod-snowflake --days 30
Credit Analysis (last 30 days):
Daily Usage Trend:
Feb 1: ββββββββββββββββββββ 28.4 credits
Feb 2: ββββββββββββββββββββ 35.1 credits
...
Feb 26: ββββββββββββββββββββ 42.7 credits
By Warehouse:
TRANSFORM_WH (XL): 523.1 credits (62%) β largest cost driver
ANALYTICS_WH (M): 187.3 credits (22%)
LOADING_WH (S): 89.4 credits (11%)
DEV_WH (XS): 47.4 credits (6%)
Recommendations:
1. TRANSFORM_WH runs at 23% utilization, consider downsizing to L
2. 340 queries on ANALYTICS_WH scan >1GB but return <100 rows, add filters
3. DEV_WH has 0 queries between 2am-8am, enable auto-suspend
finops_expensive_queriesΒΆ
Find your most expensive queries ranked by cost.
> finops_expensive_queries prod-snowflake --days 7 --limit 5
Top 5 Expensive Queries:
1. 89.3 credits | 47 executions | TRANSFORM_WH
SELECT * FROM events e JOIN users u ON e.user_id = u.id
Anti-patterns: SELECT_STAR, MISSING_LIMIT
Fix: Add column list + date filter β estimated 71% savings
2. 45.1 credits | 1 execution | TRANSFORM_WH
CREATE TABLE daily_snapshot AS SELECT DISTINCT ...
Anti-patterns: None (legitimate full-table operation)
Suggestion: Use incremental logic instead of full refresh
3. 23.7 credits | 312 executions | ANALYTICS_WH
SELECT COUNT(DISTINCT user_id) FROM events WHERE ...
Anti-patterns: None
Suggestion: Pre-aggregate in a materialized view, which saves ~23 credits/week
4. 18.2 credits | 7 executions | TRANSFORM_WH
INSERT INTO daily_agg SELECT ... FROM raw_events
Anti-patterns: SELECT_STAR_IN_SUBQUERY
Fix: Explicit columns β estimated 40% savings
5. 12.8 credits | 3 executions | ANALYTICS_WH
SELECT * FROM raw_clickstream WHERE event_type = 'page_view'
Anti-patterns: SELECT_STAR
Fix: Add column list + LIMIT β estimated 80% savings
finops_warehouse_adviceΒΆ
Get warehouse sizing recommendations based on actual usage patterns.
> finops_warehouse_advice prod-snowflake --days 14
Warehouse Analysis:
TRANSFORM_WH (currently: X-Large)
Avg utilization: 23%
Peak utilization: 67% (Wed 2-4am during batch jobs)
Avg queue time: 0.3s
Recommendation: β Downsize to LARGE
Estimated savings: 210 credits/month ($630/month)
ANALYTICS_WH (currently: Medium)
Avg utilization: 71%
Peak utilization: 95% (Mon-Fri 9am-12pm)
Avg queue time: 4.2s during peak
Recommendation: β Keep current size, enable auto-scaling (max 2 clusters)
Estimated impact: Queue time drops to <1s during peak
LOADING_WH (currently: Small)
Avg utilization: 45%
Peak utilization: 89% (daily at 6am)
Recommendation: β Keep current size
Auto-suspend: Currently 5min, recommend 1min (saves 12 credits/month)
DEV_WH (currently: X-Small)
Avg utilization: 8%
Active hours: 9am-6pm weekdays only
Recommendation: β Keep size, set auto-suspend to 1min
Estimated savings: 15 credits/month
finops_unused_resourcesΒΆ
Find tables and warehouses that are costing money but not being used.
> finops_unused_resources prod-snowflake --days 30
Unused Tables (no reads in 30 days):
1. RAW.LEGACY_EVENTS (450GB, last accessed 2025-11-03)
2. STAGING.STG_OLD_USERS (12GB, last accessed 2025-12-15)
3. ANALYTICS.TMP_MIGRATION_2024 (89GB, last accessed 2025-08-22)
Total storage: 551GB β ~$23/month in storage costs
Idle Warehouses (no queries in 7+ days):
1. MIGRATION_WH (Medium), last query 2026-02-10
2. TEST_WH (Small), last query 2026-01-28
Recommendations:
1. Archive or drop the 3 unused tables β save $23/month
2. Suspend MIGRATION_WH and TEST_WH β save credits on auto-resume
finops_role_grantsΒΆ
Analyze role permissions and access patterns (RBAC).
> finops_role_grants prod-snowflake --role ANALYST_ROLE
Grants for ANALYST_ROLE:
ββββββββββββββββ¬ββββββββββββ¬βββββββββββββββββββββββββββ
β Privilege β Type β Object β
ββββββββββββββββΌββββββββββββΌβββββββββββββββββββββββββββ€
β USAGE β WAREHOUSE β ANALYTICS_WH β
β USAGE β DATABASE β ANALYTICS β
β USAGE β SCHEMA β ANALYTICS.MARTS β
β SELECT β TABLE β ANALYTICS.MARTS.* β
β SELECT β TABLE β ANALYTICS.STAGING.* β
β USAGE β SCHEMA β ANALYTICS.RAW β
β SELECT β TABLE β ANALYTICS.RAW.* β
ββββββββββββββββ΄ββββββββββββ΄βββββββββββββββββββββββββββ
Privilege Summary:
SELECT on 847 tables across 3 schemas
No INSERT/UPDATE/DELETE privileges β
No DDL privileges β
finops_role_hierarchyΒΆ
Visualize role inheritance.
> finops_role_hierarchy prod-snowflake
Role Hierarchy:
ACCOUNTADMIN
βββ SYSADMIN
β βββ TRANSFORM_ROLE
β β βββ DBT_ROLE
β βββ LOADING_ROLE
β βββ ADMIN_ROLE
βββ SECURITYADMIN
β βββ USERADMIN
βββ PUBLIC
βββ ANALYST_ROLE
βββ VIEWER_ROLE
8 roles total
finops_user_rolesΒΆ
List user-to-role assignments.
> finops_user_roles prod-snowflake
ββββββββββββββββββββ¬βββββββββββββββββ¬ββββββββββββββββ
β User β Role β Default Role β
ββββββββββββββββββββΌβββββββββββββββββΌββββββββββββββββ€
β alice@company.comβ ANALYST_ROLE β YES β
β alice@company.comβ VIEWER_ROLE β NO β
β bob@company.com β TRANSFORM_ROLE β YES β
β bob@company.com β DBT_ROLE β NO β
β svc_dbt β DBT_ROLE β YES β
β svc_fivetran β LOADING_ROLE β YES β
ββββββββββββββββββββ΄βββββββββββββββββ΄ββββββββββββββββ