Data Observability 2.0, Part 1: Semantic Data Observability, RAG Pipeline Drift

Part 2 designs an end-to-end observability architecture and flows, showing how Monte Carlo, Great Expectations, and custom RAG metrics code detect silent failures across data harvesting, BI, feature stores, and embeddings.

Introduction: When “Green Pipelines” Still Ship Bad Data

Modern data and AI stacks are full of green DAGs, successful dbt runs, and healthy cluster metrics,while dashboards, models, and RAG systems quietly degrade.

The core problem is silent failures: defects that don’t crash jobs or throw obvious errors, but corrupt semantics, coverage, or timeliness of data and AI signals.

Data Observability 2.0 is the discipline of using AI-driven anomaly detection and contracted expectations to detect and remediate these silent failures before they propagate into BI, ML, or retrieval‑augmented generation (RAG) systems.

What Are Silent Failures? Concrete Patterns

Silent failures surface everywhere in production pipelines:

  • Volume anomalies: A job runs fine but loads 50k rows instead of the usual 500k.
  • Null-rate drift: email completeness drops from 98% to 90%, yet all jobs succeed.
  • Schema drift without errors: A source flips numeric units or renames a key field; type-compatible transforms keep running but business metrics distort.
  • Feature freshness gaps: A feature store table updates but one feature column stops changing due to a join bug.
  • Embedding drift: The same text produces different embeddings over time due to preprocessing and model changes, subtly degrading retrieval quality.

Beyond obvious anomalies, many organizations face silent data corruption: data that is structurally valid, passes basic checks, and yet is semantically wrong, often due to hardware faults, subtle software bugs, or misconfigurations that never trip standard error paths. A simple nullrate drop in a critical field (like email or customer_id) or a small embedding shift in a RAG pipeline looks statistically plausible in isolation, so it flows through ingestion jobs, data lakes, and feature stores without raising infrastructure alerts.

Once these corrupted signals are materialized and reused, joined into fact tables, aggregated into KPIs, fed into training sets, or indexed into vector databases, they compound statistical error at every downstream hop, distorting BI reports, model behavior, and LLM retrieval quality long before any CPU, disk, or orchestration monitoring shows a problem. Data Observability 2.0 treats this as a core risk: by continuously tracking null rates, distribution drift, feature/embedding drift, and retrieval metrics, and tying them to lineage, it surfaces the propagation of silent data corruption as a firstclass incident rather than a latent, months‑later surprise.

These failures are dangerous precisely because orchestration tools and infra monitors rarely catch them; traditional monitoring is blind to semantics and statistical behavior.

Data Observability 1.0 vs. 2.0 Architectural View

1.0: Infra & Job Status

Data Observability 1.0 focused on:

  • Pipeline job success/failure.
  • CPU, memory, disk, cluster health.
  • Occasionally row-count checks per batch.

It helped avoid loud failures but ignores subtle correctness and drift issues that dominate modern data/AI reliability.

2.0: End-to-End Semantic Observability

Data Observability 2.0 introduces end-to-end semantic monitoring and AI-based anomaly detection across:

  • Raw ingestion and data harvesting.
  • Transforms and semantic models.
  • Feature stores and ML training/inference.
  • Embeddings, vector stores, and RAG retrieval quality.

High-Level Architecture

Every box emits observability signals:freshness, volume, schema, distribution, drift and the observability layer uses AI to detect anomalies and drive alerting/remediation.

The Five Observability Dimensions

Most modern data observability frameworks converge on five core dimensions: freshness, volume, schema, distribution, and lineage.

These dimensions generalize cleanly across warehouses, lakes, feature stores, and even embedding indexes, and they form the backbone of Data Observability 2.0

Freshness

Definition: how recent data is relative to expectations. Freshness measures how recent the latest record is relative to your SLA (for example, “no more than 120 minutes stale for 99.5% of hours”).

Typical implementation:

  • Measure MAX(created_at) or last successful run time per table.
  • Compare to SLOs (“no more than 120 minutes stale”).

Example SQL metric for freshness:

-- Compute freshness in minutes for a key table 
SELECT 
    DATE_DIFF('minute', MAX(created_at), CURRENT_TIMESTAMP) AS freshness_minutes 
FROM analytics.fct_orders; 

However, running MAX(created_at) over multiterabyte tables without partition pruning will force a full table scan, leading to high cost and latency in engines like BigQuery and Snowflake.

In production, prefer partitionaware queries or metadata tables:

  • Filter on the partitioning column (e.g., WHERE created_date >= CURRENT_DATE - 1), so the engine prunes unnecessary partitions.
  • Use INFORMATION_SCHEMA.PARTITIONS or custom metrics tables to read freshness from table metadata rather than scanning data directly.
  • Enforce require_partition_filter = TRUE on large partitioned tables to prevent accidental unbounded scans.

Observability code should therefore treat the above SQL as a metric pattern, and in real deployments always layer partition filters or metadata lookups on top.

Volume

Definition: row counts per window relative to historical baselines. Volume observability ensures that row counts per batch or per window remain within expected ranges; a 10× drop or spike is often an early signal of upstream issues.

Example SQL metric for volume:

SELECT 
    DATE(run_date)         AS run_date, 
    COUNT(*)               AS row_count 
FROM raw.customer_events 
GROUP BY DATE(run_date) 
ORDER BY run_date DESC 
LIMIT 30;

Again, running COUNT(*) over an unpartitioned multi‑terabyte table will scan all data and can be prohibitively expensive.

In production, volume metrics should be computed in a partition-aware, costcontrolled manner:

  • Query only the relevant partitions (e.g., last N days) via a direct filter on the partitioning column or _PARTITIONDATE/_PARTITIONTIME.
  • Persist per‑partition or per‑run row counts into a lightweight metrics table, and have observability jobs read from that instead of repeatedly scanning the raw data.
  • Use dry runs and maximum bytes billed limits (BigQuery) or warehouse resource limits to guard against runaway full scans.

The outcome is that freshness and volume checks remain cheap and fast, so you can run them frequently without exploding your BigQuery or Snowflake bill, while still feeding rich metrics into Monte Carlo‑style anomaly detectors.

Schema

Definition: structure of tables: columns, types, constraints plus semantic meaning via data contracts.

Checks include:

  • Column addition/removal/rename.
  • Type changes and constraint changes.
  • Contract violations (e.g., business keys missing).

Platforms like Monte Carlo and lineage tools expose schema change alerts and their downstream impact.

Distribution

Definition: statistical shape of values (means, quantiles, histograms, categorical frequencies).

Distribution monitoring detects:

  • Unit changes (e.g., cents → dollars).
  • Population shifts (e.g., country mix or product mix changes).
  • Unexpected spikes in nulls, outliers, or categorical skew.

Lineage

Definition: explicit dependency graph connecting datasets, jobs, features, models, and indexes.

Lineage powers root-cause analysis: when a downstream asset breaks, you can trace to upstream changes and incidents.

Code Example: Detecting Email Null-Rate Drift with Great Expectations

Great Expectations (GX) lets you define expectations as code, ideal for catching silent failures like a drop in email completeness.

Scenario:

Baseline email non-null rate ≈ 98%; you want to detect if it falls below 95%.

GX code (Python) for a warehouse table – Fluent API:

import great_expectations as gx 

import great_expectations.expectations as gxe 

  

# 1. Create / load Data Context 

context = gx.get_context() 

  

# 2. Register a Postgres datasource using the Fluent API 

CONNECTION_STRING = "postgresql+psycopg2://user:pass@host:5432/analytics" 

  

datasource = context.data_sources.add_postgres( 

    "analytics_postgres", 

    connection_string=CONNECTION_STRING, 

) 

  

# 3. Attach a table asset (warehouse table) to the datasource 

customer_dim_asset = datasource.add_table_asset( 

    name="customer_dim_asset", 

    table_name="customer_dim", 

) 

  

# 4. Define a BatchDefinition (whole table, or partitioned in real setups) 

batch_definition = customer_dim_asset.add_batch_definition_whole_table( 

    "customer_dim_whole_table", 

) 

  

# 5. Create an Expectation Suite 

suite_name = "customer_dim_completeness_suite" 

suite = gx.core.expectation_suite.ExpectationSuite(name=suite_name) 

  

# Email completeness expectation: at least 95% non-null 

suite.add_expectation( 

    gxe.ExpectColumnValuesToNotBeNull( 

        column="email", 

        mostly=0.95, 

    ) 

) 

  

# Optionally add more expectations (PK uniqueness, type checks, etc.) 

suite.add_expectation( 

    gxe.ExpectColumnValuesToBeUnique(column="customer_id") 

) 

  

# Register the suite with the context 

context.suites.add(suite) 

  

# 6. Wire the BatchDefinition and Suite together via a ValidationDefinition 

validation_definition = context.validation_definitions.add( 

    gx.core.validation_definition.ValidationDefinition( 

        name="customer_dim_validation", 

        data=batch_definition, 

        suite=suite, 

    ) 

) 

  

# 7. Create a Checkpoint and run validation 

checkpoint = context.checkpoints.add( 

    gx.checkpoint.checkpoint.Checkpoint( 

        name="customer_dim_checkpoint", 

        validation_definitions=[validation_definition], 

    ) 

) 

  

result = checkpoint.run() 

  

if not result.success: 

    # Fail the pipeline or emit an incident into your observability stack 

    raise RuntimeError("GX validation failed: email completeness or uniqueness expectations not met") 

This uses the Fluent Datasources API (context.data_sources.add_postgres, add_table_asset, add_batch_definition_whole_table) and Validation Definition / Checkpoint flow that GX 1.0+ recommends, instead of the legacy SqlAlchemyDataset pattern.

If you want a more “Validator‑centric” style (especially when integrating with orchestrators), you can also obtain a Validator with a batch_request and call validator.expect_* directly, but the above checkpoint pattern fits well with CI/CD and production observability workflows.

Extending Observability Beyond BI: Features, Embeddings, Retrieval

Data Observability 2.0 explicitly extends observability to AI features, embeddings, and retrieval quality.

Feature Stores & ML Pipelines

Key checks:

  • Feature freshness (time since last update per feature column).
  • Feature completeness (null-rate drift).
  • Feature distribution drift vs training baselines.

Python sketch for drift detection on a feature:

import pandas as pd 
from scipy.stats import ks_2sample 
 
# historical training baseline 
train_feature = pd.read_parquet("train/churn_features.parquet")["days_since_last_login"] 
live_feature  = pd.read_parquet("live/churn_features.parquet")["days_since_last_login"] 

 

# KS works well for continuous 1D features; for categorical or high-dimensional vectors, # prefer PSI or Wasserstein / MMD-style distances to avoid noisy, false-positive drift alerts. 
 
stat, p_value = ks_2sample(train_feature, live_feature) 
 
if p_value < 0.01: 
    print("Significant feature drift detected for days_since_last_login") 
    # Trigger incident, adjust model, or flag for retraining 

Embeddings & RAG Retrieval Quality

Silent failures here are dominated by embedding drift and retrieval drift:

  • Cosine distance between “old” and “new” embeddings of the same text grows over time.
  • Nearest-neighbor overlap declines; queries hit different documents for the same intent.
  • Recall@K and nDCG drop on golden queries.

We’ll go deeper with code and flows in later parts, but the key idea in Part 1 is: observability must treat embeddings and retrieval metrics as firstclass signals, not just model accuracy.

Part 1 Conclusion & Transition

Silent failures are not edge cases; they are the dominant failure mode in modern data and AI stacks.

Execution‑level monitoring tells you that pipelines ran, but semantic observability tells you whether the data, features, embeddings, and retrievals are actually correct, complete, and fresh.

By formalizing the five dimensions freshness, volume, schema, distribution, and lineage and extending them beyond BI into feature stores and RAG layers, Data Observability 2.0 becomes a first-class architectural concern, not an afterthought. The GX example for email completeness is a small but concrete demonstration of how to turn silent failures into explicit, testable contracts that stop bad data at the boundary.

In Part 2, we move from principles to systems.

We will design an end‑to‑end observability architecture with concrete flows, showing how Monte Carlo‑style anomaly detection, Great Expectations, and AI/RAG‑aware monitors plug into ingestion, transformation, feature, and embedding layers.

You will see how to instrument your stack so that every critical hop data harvest, transform, feature computation, vector search produces machinereadable signals that AI can use to detect silent failures in real time.

- Authored by Sonal Dwevedi & Tharun Mathew