Skip to main content

How Datacoves Billing Works

This page explains how Datacoves measures and bills Airflow worker usage, what is and isn't included in billed minutes, and how billed usage relates to Airflow's own metadata.

Overview

Datacoves bills Airflow usage based on worker pod running time. Each Airflow task runs inside a dedicated Kubernetes pod, and billing is based on how long that pod is alive in the cluster. This is different from the task durations shown in the Airflow UI, which only reflects when task code itself was running.

Billing is derived from the Prometheus metric:

kube_pod_container_status_running

This metric captures the time each worker pod container spends in the Running state. The total is summed across all pods in your environment to produce your monthly billed minutes.

Task execution timeline

A typical task goes through eight stages from the moment it is enqueued to the moment its pod is decommissioned. Only some of these stages are billed.

#StageDescriptionBilled
1Task Enqueuedqueued_dttm: task is in the scheduler queue; no pod exists yet.No
2Pod CreationPod is created in Pending state; includes image pulling.No
3Init Containergit-sync runs to clone or sync the repository.Yes
4Main Container StartPod transitions to Running state.Yes
5Airflow BootstrapThe worker process initializes and loads the environment.Yes
6Task Executionstart_date: the actual task / DAG code begins running.Yes
7Task Completionend_date: the task code finishes its execution.Yes
8Pod TerminationThe container stops and the pod is decommissioned.No

Task Execution Timeline and Billing Logic

Billing starts when the main container reaches Running and ends when the pod terminates. Queue time, pod creation, and image pulls are not billed.

How this maps to Airflow metadata

The task_instance table in the Airflow metadata database has three timestamp columns relevant here:

ColumnDescription
queued_dttmWhen the task was placed in the queue
start_dateWhen the task code actually started executing
end_dateWhen the task code finished executing

Comparing those columns to billed time:

CalculationWhat it capturesRelation to billing
end_date - queued_dttmQueue time + pod init + bootstrap + executionOverestimates billed minutes
end_date - start_dateTask code execution onlyUnderestimates billed minutes
Billed (pod running)Init container + Main container start + bootstrap + execution + completionActual billed value

Neither Airflow column on its own matches the billed value exactly. The billed value sits between the two.

Querying the Airflow task_instance table

To estimate usage directly from Airflow metadata:

  • queued_dttm to end_date (queued_plus_execution_time) overestimates billed minutes.
  • start_date to end_date (execution_time) underestimates billed minutes.

The actual billed figure falls inside that range.

Example query:

SELECT
date_trunc('day', ti.start_date) AS day,
count(*) AS tasks,
round(sum(EXTRACT(EPOCH FROM (ti.end_date - ti.queued_dttm)) / 60)::numeric, 1) AS queued_plus_execution_time,
round(sum(EXTRACT(EPOCH FROM (ti.end_date - ti.start_date)) / 60)::numeric, 1) AS execution_time,
round(sum(EXTRACT(EPOCH FROM (ti.start_date - ti.queued_dttm)) / 60)::numeric, 1) AS queue_time_min
FROM task_instance ti
WHERE ti.state = 'success'
AND ti.start_date >= '2026-03-01 00:00:00+00'
AND ti.start_date < '2026-04-01 00:00:00+00'
AND ti.queued_dttm IS NOT NULL
AND ti.end_date IS NOT NULL
GROUP BY 1
ORDER BY 1;