What you will be able to do
- Query system.access.audit to answer who-did-what questions, and explain its regional scope and masked parameters
- Name the six system.lakeflow tables and say which are SCD2 dimension tables and which are immutable timelines
- Write a query that returns the current state of jobs or tasks, excluding deleted ones, from an SCD2 table
- Use the run timeline tables to monitor run outcomes and the compute each task used
1.Auditing account activity with system.access.audit
Billing tells you what was spent. system.access.audit tells you who did what. The table is in Public Preview and records audit events from the workspaces in your region. Each row is one event, made up of the service that handled it, the action, the person or principal who called it, the parameters they sent and the response they got.
| Column | Meaning | Example |
|---|---|---|
| event_date | Calendar date of the action; filter on this for performance | 2023-01-01 |
| event_time | Timestamp of the event (UTC) | 2023-01-01T01:01:01.123+00:00 |
| user_identity | Identity of user initiating request | {"email": "user@domain.com", "subjectName": null} |
| service_name | Service name initiating request | unityCatalog |
| action_name | Category of the event captured in audit log | getTable |
| request_params | Map of all the request parameters | full_name_arg, workspace_id, metastore_id |
| response | Struct of response return values | {"statusCode": 200, "errorMessage": null, "result": null} |
| audit_level | Workspace or account level event | ACCOUNT_LEVEL |
| source_ip_address | IP address where the request originated | 10.30.0.242 |
Four details affect how you query it:
- Partition by date. Filter on event_date, not event_time, to improve query performance.
- Scope. Workspace-level events are regional. Account-level events are global and record workspace_id as 0, so an account-level action won't show up under a workspace ID filter.
- Masking. Some events store SQL definitions in request_params under keys such as view_definition and function_info. Those keys are omitted unless you are an account admin or a member of the databricks_pii_access group. Other keys and columns are unchanged.
- Workspace deletion. When a workspace is deleted, its audit events older than 14 days are removed from the table, so export anything you must keep before decommissioning a workspace.
Checkpoint 1 of 7· Check yourself
An auditor filters system.access.audit on a specific workspace_id and can't find an account-level administrative action they know took place. Why?
Account-level audit logs record workspace_id as 0, so a filter on a real workspace ID excludes them. databricks_pii_access only unmasks SQL definition keys in request_params.
“Account-level audit logs record workspace_id as 0.”Source: docs.databricks.com
Checkpoint 2 of 7· Exam question
A security team suspects that a service principal exported large tables outside normal business hours. They plan to investigate using `system.access.audit`, which records `event_time`, `service_name`, `action_name`, `user_identity`, `request_params`, `response`, and `audit_level` for every logged event. Which two filters should they combine to surface the suspicious export events? (Choose two)(Select 2)
Correct answers: A, B — Filter `action_name` to the export/download action for large result retrievals, and restrict `event_time` to hours outside the organization's normal working window.; Filter `user_identity.email` (or application ID) to the specific service principal under investigation, so only that principal's audit trail is examined for the behavior.
- A. Narrowing to the export or download action along with an off-hours time window isolates exactly the class of event the team suspects: a large data retrieval happening when legitimate business activity is unlikely, which is the core signal for this investigation.
- B. Scoping the audit trail to the specific service principal's identity removes noise from unrelated users and workloads, letting the team focus only on the events attributable to the principal under suspicion.
- C. A status code of 200 only means the request completed successfully; it is recorded for logins, queries, and countless benign actions, so filtering on it alone cannot distinguish a table export from any other successful operation.
- D. Cluster lifecycle events describe compute start/stop activity, not data access, so filtering to the clusters service does not reveal which tables were read or exported and misses the actual export action entirely.
- E. Filtering only by the catalog path without also restricting identity or action returns every event touching that path, including unrelated reads and administrative actions, which buries the suspicious export among irrelevant rows.
- F. Audit records are not scoped so that service-principal exports are excluded from workspace-level logging; this filter rests on an incorrect assumption about how the table captures events and would exclude the very rows the team needs.
Sources1
2.The system.lakeflow schema: jobs, tasks, pipelines and their timelines
For workload monitoring, the main schema is system.lakeflow, which was previously called workflow. Both schemas have identical content, so older queries against system.workflow still match. The tables are regional: to see another region's jobs, you query from a workspace deployed in that region. Job tables typically get records within one hour, which is much fresher than billing data.
| Table | Tracks | Kind |
|---|---|---|
| jobs | All jobs created in the account | SCD2 (key: workspace_id, job_id) |
| job_tasks | All job tasks that run in the account | SCD2 (key: workspace_id, job_id, task_key) |
| job_run_timeline | Job runs and related metadata | Immutable |
| job_task_run_timeline | Job task runs and related metadata | Immutable |
| pipelines (Public Preview) | All pipelines created in the account | SCD2 (key: workspace_id, pipeline_id) |
| pipeline_update_timeline (Public Preview) | Pipeline updates and related metadata | Immutable |
Checkpoint 3 of 7· Check yourself
Which of these system.lakeflow tables is an immutable timeline that needs no deduplication?
jobs, job_tasks and pipelines are SCD2 tables that emit a new row on every change. The run and update timeline tables are immutable, so they need no deduplication.
“The job run timeline, job task run timeline, and pipeline update timeline tables are immutable, so they need no deduplication.”Source: docs.databricks.com
The jobs table also stores the definition fields you'll want to audit, including run_as_user_name, creator_user_name, paused, timeout_seconds, health_rules and trigger_type (MULTIPLE when a job has several triggers). Many of these columns aren't populated for rows emitted before early December 2025, so null values in older history are expected and don't mean the data is bad.
Sources2
3.Querying current state from SCD2 tables
jobs, job_tasks and pipelines never update a row. Each change adds a new row with a new change_time, and a deletion adds a row with delete_time populated. A plain SELECT * FROM system.lakeflow.jobs therefore returns every historical version of every job. To get current state, take the latest row per entity key, and only after that drop rows that record a deletion.
-- Get the current state of every job, excluding deleted jobs
with latest AS (
SELECT
*,
ROW_NUMBER() OVER(PARTITION BY workspace_id, job_id ORDER BY change_time DESC) as rn
FROM
system.lakeflow.jobs QUALIFY rn=1
)
SELECT * FROM latest WHERE delete_time IS NULLCheckpoint 4 of 7· Put it in order
Put the steps for getting the current, non-deleted state of entities from an SCD2 table in order
- 1.Exclude rows where delete_time is populated
- 2.Partition rows by the table's entity key (e.g. workspace_id, job_id)
- 3.Order each partition by change_time descending and keep only the first row
Deletion is itself the latest row. If you filter delete_time before choosing the latest row, the deletion row is discarded and the entity's last pre-deletion state comes back as if it were current.
“take the row with the most recent change_time, then exclude the rows that record a deletion”Source: docs.databricks.com
Checkpoint 5 of 7· Fill the gap
job_tasks is keyed below the job level. Which column completes the partition key?
-- Get the most recent version of each job task
SELECT
*,
ROW_NUMBER() OVER(PARTITION BY workspace_id, job_id, ? ORDER BY change_time DESC) as rn
FROM
system.lakeflow.job_tasks QUALIFY rn=1A task is identified by task_key, which is unique only within a job, so the entity key is workspace_id, job_id, task_key. run_id and job_run_id identify runs, which live in the timeline tables.
Source: docs.databricks.comCheckpoint 6 of 7· Exam question
Monthly compute spend has spiked. An engineer joins `system.compute.clusters` to `system.billing.usage` and finds several all-purpose clusters with `autotermination_minutes = 0` running continuously under a shared `owned_by` service principal that no longer maps to an active team. What is the most effective first remediation based on this system table data?
Correct answer: A — Set an autotermination window on the clusters and update `owned_by` to the team that uses them, so idle time stops accruing and future usage attributes correctly.
- A. Enforcing autotermination directly removes the root cause of idle spend, and correcting `owned_by` restores accountability so the team responsible can monitor and control the cluster's cost going forward.
- B. System tables are read-only records generated by the platform from actual account activity; deleting rows from them is not a supported operation and would not stop the underlying cluster from continuing to accrue real charges.
- C. Raising `min_workers` forces the autoscaler to keep more workers running at all times, which increases baseline cost rather than reducing it, and does nothing to address a cluster that never terminates.
- D. `system.billing.list_prices` is a reference table of historical SKU rates published by Databricks; it cannot be written to in order to negotiate a lower price, and utilization data has no mechanism to trigger a repricing through this table.
Sources2
4.Monitoring runs with the timeline tables
The timeline tables record what actually ran. job_run_timeline, job_task_run_timeline and pipeline_update_timeline are immutable and complete when produced, so they need no deduplication. Long runs are split into hourly slices across several rows, each bounded by period_start_time and period_end_time, and availability is measured from period_end_time.
In job_task_run_timeline, each row carries job_id, job_run_id, run_id (the task run) and task_key. The compute_ids array lists the job clusters, interactive clusters and SQL warehouses the task used, which lets you join a task's runtime to system.compute and, through cluster_id, to its billing rows. Because of hourly slicing, result_state is filled only on the row that represents the end of the run. When you count failures, filter or aggregate on that row; don't count every slice.
Checkpoint 7 of 7· Check yourself
A task ran for three hours and failed. In job_task_run_timeline it spans several rows. Where do you find its outcome?
Runs longer than an hour are sliced into multiple rows, and the outcome is written only on the final slice. Counting result_state across all rows would either miss the outcome or count it wrongly.
“this column is populated only in the row that represents the end of the run”Source: docs.databricks.com
Sources2
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.Adding WHERE delete_time IS NULL directly to the query that reads system.lakeflow.jobs removes deleted jobs.Why is that wrong?
Filtering delete_time in the same pass discards the deletion row, so the job's last pre-deletion version is returned as if it were current. Select the latest row first, then filter.
Covered in Querying current state from SCD2 tables
2.system.access.audit is global like system.billing.usage, so one query from any workspace sees every region's events.Why is that wrong?
Audit data is regional for workspace-level events. Only account-level events are global.
Covered in Auditing account activity with system.access.audit
Practise it for real
Build a current-state inventory of jobs and tasks from system.lakeflow and confirm that deleted jobs are excluded
1.Run SELECT COUNT(*) FROM system.lakeflow.jobs and compare it with the number of jobs you see in the Jobs UI.
Why: jobs is an SCD2 table, so every edit and deletion adds a row.
You should see: The count is higher than your number of jobs because the table holds every historical version.
2.Run the 'current state of every job, excluding deleted jobs' query from this page.
Why: ROW_NUMBER over workspace_id, job_id ordered by change_time DESC keeps the latest version, and the outer filter removes deleted jobs.
You should see: One row per live job, matching the jobs you can see.
3.Move the delete_time IS NULL filter inside the CTE and run the query again.
Why: This shows the ordering trap: the deletion row is filtered out before the latest row is chosen.
You should see: Deleted jobs reappear, showing their last state before deletion.
4.Adapt the query to system.lakeflow.job_tasks, partitioning by workspace_id, job_id, task_key.
Why: Each SCD2 table has its own entity key.
You should see: One row per live task per job.
Stuck? Get a nudge
If step 3 returns the same rows as step 2, check whether anyone has deleted a job in the last 365 days; without a deletion there's nothing for the trap to expose.
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.
“Table path: This system table is located at system.access.audit.”
↩︎ Auditing account activity with system.access.audit“To improve query performance, filter on event_date rather than event_time.”
↩︎ Auditing account activity with system.access.audit“keys in request_params that contain SQL definitions are omitted unless you are an account admin or a member of the databricks_pii_access group”
↩︎ Auditing account activity with system.access.audit“When you delete a workspace, Databricks removes that workspace's audit events that are older than 14 days from system.access.audit.”
↩︎ Auditing account activity with system.access.audit“Account-level audit logs record workspace_id as 0.”
↩︎ Checkpoint - 2.
“The lakeflow schema was previously known as workflow. The content of both schemas is identical.”
↩︎ The system.lakeflow schema: jobs, tasks, pipelines and their timelines“To see records from another region, you must view the tables from a workspace deployed in that region.”
↩︎ The system.lakeflow schema: jobs, tasks, pipelines and their timelines“records are typically available within one hour.”
↩︎ The system.lakeflow schema: jobs, tasks, pipelines and their timelines“Deletions are recorded as a new row with delete_time populated, not by removing rows.”
↩︎ Querying current state from SCD2 tables“job_tasks: workspace_id, job_id, task_key”
↩︎ Querying current state from SCD2 tables“The job run timeline, job task run timeline, and pipeline update timeline tables are immutable, so they need no deduplication.”
↩︎ Monitoring runs with the timeline tables“The compute_ids array contains IDs of job clusters, interactive clusters, and SQL warehouses used by the job task”
↩︎ Monitoring runs with the timeline tables“For the job_run_timeline and job_task_run_timeline tables, availability is measured from the period_end_time column.”
↩︎ Monitoring runs with the timeline tables“Filtering delete_time in the same query that reads the table returns each deleted entity's last state before deletion instead of omitting the entity.”
↩︎ Exam trap 1“The job run timeline, job task run timeline, and pipeline update timeline tables are immutable, so they need no deduplication.”
↩︎ Checkpoint“Databricks retains the most recent record for each entity in the slowly changing dimension (SCD2) tables (jobs, job_tasks, and pipelines).”
↩︎ Prediction“take the row with the most recent change_time, then exclude the rows that record a deletion”
↩︎ Checkpoint“this column is populated only in the row that represents the end of the run”
↩︎ Checkpoint
Also cited
“Regional for workspace-level events. Global for account-level events.”
↩︎ Exam trap 2