# an illustration with made-up numbers
dbu_per_hour = 4 # depends on the compute size
price_per_dbu = 0.50 # placeholder: SKU and plan decide this
hours = 2.5
databricks_cost = dbu_per_hour * price_per_dbu * hours
print(round(databricks_cost, 2)) # 5.0 (plus VM cost if classic compute)
Module 18: Cost & Resource Optimization
DBUs, compute choices, cluster policies and FinOps.
Topics in this module
- Databricks Pricing and DBUs
- Serverless vs Classic Compute
- Job vs All-Purpose Compute Costs
- Compute Sizing and Autoscaling
- Cluster Policies
- Photon Cost-Benefit Analysis
- Storage and Delta Maintenance Costs
- Job Scheduling Optimization
- SQL Warehouse Cost Optimization
- Cost Attribution and Chargeback
- FinOps Principles
- Performance vs Cost Trade-offs
Spend only what the work needs, and be able to say who spent it. Free Edition has no bill (it has a daily compute quota), so this module teaches the model and the levers. You practise the habits on the quota.
- Prices change by cloud, region and plan: never trust a number written in a course. The examples use made-up rates, labelled as such
- Four levers cover most savings: right compute type, right size, less data read, fewer idle hours
Databricks Pricing and DBUs
By the end: explain how Databricks pricing and DBUs work.
| Term | Meaning |
|---|---|
| DBU | Databricks Unit: a measure of processing used per hour |
| SKU | The product billed (jobs, all-purpose, SQL, serverless...), each with its own price per DBU |
| Cloud cost | VMs, storage, network on classic compute: billed by your cloud |
| List price | Public price before any discount or commitment |
- Different products have different DBU prices: job compute is cheaper than all-purpose
- Serverless includes the compute: one bill, no VMs to manage
- Check the official pricing page for real rates
- On Free Edition nothing is billed: you have a daily quota instead
Remember
Cost = (DBUs per hour × price per DBU × hours) + cloud cost on classic. Cut the hours first.
Serverless vs Classic Compute
By the end: decide between serverless and classic compute.
| Choose | When |
|---|---|
| Serverless | Bursty, interactive, short jobs, small teams, little ops capacity |
| Serverless, standard mode | Scheduled jobs that can wait 4–6 minutes to start (lower cost) |
| Classic | Steady heavy workloads you can tune, spot instances, special hardware (GPU) or network needs |
- Serverless performance-optimized keeps warm resources for fast starts: the default for interactive
- Serverless notebooks stop after a default 2.5-hour execution timeout: an overspend guard
- Serverless needs no tuning of nodes, but your code and data layout still decide the cost
- Compare total cost: classic VMs + DBUs + engineers' time, against serverless
Free Edition
Serverless only, so compare these options on paper.
Job vs All-Purpose Compute Costs
By the end: know why job compute is cheaper than all-purpose compute.
| All-purpose | Job compute | SQL warehouse | |
|---|---|---|---|
| For | Interactive development | Scheduled, automated work | SQL, BI, dashboards |
| Lifetime | Stays up until stopped | Created for the run, ends after | Starts and stops on demand |
| Price per DBU | Higher | Lower | By warehouse type |
- Develop interactively, run as a job (Module 10)
- A forgotten all-purpose cluster is the classic waste: set auto termination
- Notebooks that run daily belong in a job, not in a notebook someone keeps open
- On serverless the same rule applies as a habit: don't leave long interactive sessions open
- Use one job with many tasks sharing compute, not many small jobs that each start their own
Interactive for building, jobs for running
It is also the cheapest split.
Compute Sizing and Autoscaling
By the end: size compute and use autoscaling properly.
- Cost is size × time. Doubling the size can halve the time at the same cost, so a bigger cluster is not always dearer
- Look for spill (too little memory), low CPU use (too big) and skew (one slow task: more nodes won't help)
- Autoscaling adds and removes workers with demand. Use it for varying loads. Streaming jobs usually need fixed size
- Pools keep warm instances: faster starts, no DBU charges while idle (but VM costs continue)
- Spot instances for workers are much cheaper: keep the driver on-demand
- For SQL warehouses: start with one size, move up if queries spill, add clusters only for concurrency
Fix the query first
A skewed join stays slow on a bigger cluster. Check the profile before scaling (Module 12).
Cluster Policies
By the end: enforce guardrails with compute policies.
{
"autotermination_minutes": { "type": "fixed", "value": 30 },
"autoscale.max_workers": { "type": "range", "maxValue": 8 },
"node_type_id": { "type": "allowlist", "values": ["m5.xlarge", "m5.2xlarge"] },
"custom_tags.team": { "type": "unlimited" },
"dbus_per_hour": { "type": "range", "maxValue": 20 }
}
| Rule type | Does |
|---|---|
fixed |
Locks a value (and can hide it) |
allowlist / blocklist |
Limits choices |
range |
Sets a min or max |
regex |
Pattern for strings |
unlimited |
Makes an attribute required or sets a default |
- A policy limits what users can create: sizes, autotermination, tags, cost per hour (
dbus_per_hour) - Give people policies, not free choice. Teams get a policy per workload type
- Require tags so spend can be attributed
- Serverless usage policies do the same for serverless: they apply tags to usage
Free Edition
Policies are admin features: not available. The JSON is for reference. The node types are examples.
Photon Cost-Benefit Analysis
By the end: judge Photon on cost, not only speed.
- Photon runs some work faster, but compute with Photon costs more per hour
- It pays off when the speed-up is larger than the price difference: heavy joins, aggregations, scans, Delta writes
- It helps little for Python UDF-heavy code and very short queries (< 2 s)
- Serverless and SQL warehouses have Photon built in: the price already includes it
# decide with a measurement, not a guess:
# run the same job twice (with and without Photon), record runtime and DBUs
# cost_per_run = dbus_per_hour * price_per_dbu * runtime_hours
| Result | Do |
|---|---|
| Faster and cheaper per run | Keep Photon |
| Faster, a little dearer | Keep it if the time matters |
| No speed-up | Turn it off on classic compute |
- Test your real jobs. Test regularly: runtimes and engines change
Storage and Delta Maintenance Costs
By the end: keep storage and Delta maintenance costs under control.
%sql
DESCRIBE DETAIL orders_delta
# table sizes in the schema (views are skipped)
import pyspark.sql.functions as F
rows = []
for t in spark.sql("SHOW TABLES").collect():
if t.isTemporary:
continue
try:
d = spark.sql(f"DESCRIBE DETAIL {t.tableName}").first()
rows.append((t.tableName, d["numFiles"], d["sizeInBytes"]))
except Exception:
pass # views and non-Delta tables have no detail
df = spark.createDataFrame(rows, "table STRING, files LONG, bytes LONG")
display(df.orderBy(F.desc("bytes")))
| Storage cost driver | Fix |
|---|---|
| Old files kept by time travel | VACUUM (default 7 days) |
| Long history retention | Lower delta.deletedFileRetentionDuration only if you don't need it |
| Many small files | OPTIMIZE, predictive optimization |
| Copies of data nobody uses | Drop old tables, clones, backups |
| Duplicate bronze data | Keep one raw copy |
| Cross-region reads and sharing | Egress fees: keep compute near data |
- Predictive optimization (managed tables) runs
OPTIMIZEandVACUUMwhen it pays off: no extra schedule needed - Managed tables that are dropped can be recovered for a few days (
UNDROP), then are cleaned up - Maintenance compute costs something too: don't
OPTIMIZEevery table every hour - Delete temporary and test tables
Job Scheduling Optimization
By the end: schedule jobs to cost less.
| Lever | Saves |
|---|---|
| Fewer runs: hourly → every 4 hours, if nobody needs more | Compute hours |
Incremental processing (availableNow, MERGE of new data) |
Re-reading old data |
| Combine small jobs into tasks of one job | Startup time and idle gaps |
| Run big jobs when compute is idle | Contention, retries |
| Serverless standard mode for non-urgent jobs | Up to a large share of cost: accepts 4–6 min start |
| Triggers (file arrival) instead of frequent polling | Empty runs |
| Skip runs when there is no new data (if/else task, Module 10.8) | The downstream cost |
- Timeouts stop runaway jobs. Retries that always fail double the cost
- Pause dev schedules (bundle development mode does this)
- Continuous streaming costs 24/7: use
availableNowunless seconds of latency are a requirement
Ask how fresh it must be
Data that is read once a day doesn't need hourly refresh.
SQL Warehouse Cost Optimization
By the end: cut SQL warehouse costs.
- Auto stop short (5–10 minutes) so idle warehouses end
- Serverless warehouses start in seconds, so aggressive auto stop costs little
- Right size: bigger only if queries spill. More clusters only for concurrent users
- One warehouse per workload class (BI, ETL, ad hoc) so one noisy query doesn't force a bigger size on everyone
- Result caching serves repeated dashboard queries free of compute (Module 13.8)
- Refresh dashboards on a schedule, not on every view, and not more often than the data changes
- Materialized views and gold tables: compute once, read many times
- Find the costly queries in query history (long duration, bytes read) and fix them (Module 12)
| Warehouse | Hours/day running | Fix |
|---|---|---|
| Always on, mostly idle | 24 | Lower auto stop |
| Dashboard refresh every minute | 24 | Refresh when the data changes |
| One big shared warehouse | high | Split by workload, right-size each |
Cost Attribution and Chargeback
By the end: attribute cost to teams and projects.
%sql
-- cost units per team tag (system tables: may not exist on Free Edition)
SELECT custom_tags['team'] AS team, usage_date, sum(usage_quantity) AS dbus
FROM system.billing.usage
GROUP BY ALL
ORDER BY usage_date DESC
| Practice | Why |
|---|---|
Tag standard: team, project, env, owner |
One way to slice cost |
| Enforce tags with compute policies | No untagged spend |
| Serverless usage policies | Tag serverless usage per user or team |
| Budgets with email alerts | Notice before the month ends |
| Chargeback / showback report | Teams see their own cost |
usage_metadata.job_idlinks usage to jobs. Corrections arrive as negative rows: sum them- Showback (show costs) first, chargeback (bill them) later
- Untagged usage goes in an "unallocated" bucket that you try to drive to zero
- AI/BI cost dashboards can be imported by account admins
FinOps Principles
By the end: apply FinOps principles to data engineering.
| Principle | In practice |
|---|---|
| Teams own their cost | Dashboards by team, budgets per team |
| Visibility first | Tags, system tables, a weekly view |
| Unit economics | Cost per run, per million rows, per dashboard view |
| Automate guardrails | Policies, auto stop, timeouts |
| Review regularly | Top 10 jobs by cost, every month |
| Cost is a requirement | Part of design reviews with latency and reliability |
- Measure cost per unit of output: total spend can rise while cost per row falls
- Savings from less work (incremental, pruning) beat savings from cheaper hardware
- Keep a backlog of cost fixes, ranked by saving and effort
Performance vs Cost Trade-offs
By the end: weigh performance against cost.
| Trade-off | Cheaper | Faster |
|---|---|---|
| Compute size | Smaller | Larger (same cost if time drops in proportion) |
| Start time | Standard serverless mode | Performance-optimized |
| Freshness | Batch every few hours | Streaming, continuous |
| Read speed | Fewer copies, no pre-aggregates | Materialized views, more storage |
| Reliability | Single run | Retries, redundancy |
| Photon | Off for UDF-heavy work | On for SQL-heavy work |
- Start from the requirement: what latency, freshness and reliability does the business need?
- The cheapest design that meets the requirement wins
- Check the trade-off with a measurement on real data
- Write down the decision and the cost, so it can be reviewed
Don't buy speed nobody uses
A dashboard viewed daily doesn't need a streaming pipeline.
What you can do now
- DBUs, SKUs, serverless vs classic, job vs all-purpose
- Sizing, autoscaling, policies, Photon cost-benefit
- Storage, scheduling and SQL warehouse costs
- Tags, attribution, FinOps and trade-offs