$npx -y skills add astronomer/agents --skill checking-freshnessQuick data freshness check. Use when the user asks if data is up to date, when a table was last updated, if data is stale, or needs to verify data currency before using it.
| 1 | # Data Freshness Check |
| 2 | |
| 3 | Quickly determine if data is fresh enough to use. |
| 4 | |
| 5 | ## Freshness Check Process |
| 6 | |
| 7 | For each table to check: |
| 8 | |
| 9 | ### 1. Find the Timestamp Column |
| 10 | |
| 11 | Look for columns that indicate when data was loaded or updated: |
| 12 | - `_loaded_at`, `_updated_at`, `_created_at` (common ETL patterns) |
| 13 | - `updated_at`, `created_at`, `modified_at` (application timestamps) |
| 14 | - `load_date`, `etl_timestamp`, `ingestion_time` |
| 15 | - `date`, `event_date`, `transaction_date` (business dates) |
| 16 | |
| 17 | Query INFORMATION_SCHEMA.COLUMNS if you need to see column names. |
| 18 | |
| 19 | ### 2. Query Last Update Time |
| 20 | |
| 21 | ```sql |
| 22 | SELECT |
| 23 | MAX(<timestamp_column>) as last_update, |
| 24 | CURRENT_TIMESTAMP() as current_time, |
| 25 | TIMESTAMPDIFF('hour', MAX(<timestamp_column>), CURRENT_TIMESTAMP()) as hours_ago, |
| 26 | TIMESTAMPDIFF('minute', MAX(<timestamp_column>), CURRENT_TIMESTAMP()) as minutes_ago |
| 27 | FROM <table> |
| 28 | ``` |
| 29 | |
| 30 | ### 3. Check Row Counts by Time |
| 31 | |
| 32 | For tables with regular updates, check recent activity: |
| 33 | |
| 34 | ```sql |
| 35 | SELECT |
| 36 | DATE_TRUNC('day', <timestamp_column>) as day, |
| 37 | COUNT(*) as row_count |
| 38 | FROM <table> |
| 39 | WHERE <timestamp_column> >= DATEADD('day', -7, CURRENT_DATE()) |
| 40 | GROUP BY 1 |
| 41 | ORDER BY 1 DESC |
| 42 | ``` |
| 43 | |
| 44 | ## Freshness Status |
| 45 | |
| 46 | Report status using this scale: |
| 47 | |
| 48 | | Status | Age | Meaning | |
| 49 | |--------|-----|---------| |
| 50 | | **Fresh** | < 4 hours | Data is current | |
| 51 | | **Stale** | 4-24 hours | May be outdated, check if expected | |
| 52 | | **Very Stale** | > 24 hours | Likely a problem unless batch job | |
| 53 | | **Unknown** | No timestamp | Can't determine freshness | |
| 54 | |
| 55 | ## If Data is Stale |
| 56 | |
| 57 | Check Airflow for the source pipeline: |
| 58 | |
| 59 | 1. **Find the DAG**: Which DAG populates this table? Use `af dags list` and look for matching names. |
| 60 | |
| 61 | 2. **Check DAG status**: |
| 62 | - Is the DAG paused? Use `af dags get <dag_id>` |
| 63 | - Did the last run fail? Use `af dags stats` |
| 64 | - Is a run currently in progress? |
| 65 | |
| 66 | 3. **Diagnose if needed**: If the DAG failed, use the **debugging-dags** skill to investigate. |
| 67 | |
| 68 | ### On Astro |
| 69 | |
| 70 | If you're running on Astro, you can also: |
| 71 | |
| 72 | - **DAG history in the Astro UI**: Check the deployment's DAG run history for a visual timeline of recent runs and their outcomes |
| 73 | - **Astro alerts for SLA monitoring**: Configure alerts to get notified when DAGs miss their expected completion windows, catching staleness before users report it |
| 74 | |
| 75 | ### On OSS Airflow |
| 76 | |
| 77 | - **Airflow UI**: Use the DAGs view and task logs to verify last successful runs and SLA misses |
| 78 | |
| 79 | ## Output Format |
| 80 | |
| 81 | Provide a clear, scannable report: |
| 82 | |
| 83 | ``` |
| 84 | FRESHNESS REPORT |
| 85 | ================ |
| 86 | |
| 87 | TABLE: database.schema.table_name |
| 88 | Last Update: 2024-01-15 14:32:00 UTC |
| 89 | Age: 2 hours 15 minutes |
| 90 | Status: Fresh |
| 91 | |
| 92 | TABLE: database.schema.other_table |
| 93 | Last Update: 2024-01-14 03:00:00 UTC |
| 94 | Age: 37 hours |
| 95 | Status: Very Stale |
| 96 | Source DAG: daily_etl_pipeline (FAILED) |
| 97 | Action: Investigate with **debugging-dags** skill |
| 98 | ``` |
| 99 | |
| 100 | ## Quick Checks |
| 101 | |
| 102 | If user just wants a yes/no answer: |
| 103 | - "Is X fresh?" -> Check and respond with status + one line |
| 104 | - "Can I use X for my 9am meeting?" -> Check and give clear yes/no with context |