data-pipeline-patterns

colingwuyu's avatarfrom colingwuyu

Follow these patterns when implementing data pipelines, ETL, data ingestion, or data validation in OptAIC. Use for point-in-time (PIT) correctness, Arrow schemas, quality checks, and Prefect orchestration.

⭐0stars🔀0forks📁View on GitHub🕐Updated Jan 3, 2026

When & Why to Use This Skill

This Claude skill provides a comprehensive framework and standardized patterns for building robust data pipelines within the OptAIC ecosystem. It ensures data integrity through Point-in-Time (PIT) correctness, enforces structural consistency with Arrow schemas, and streamlines workflow management using Prefect orchestration and automated lineage tracking. By following these architectural blueprints, developers can eliminate lookahead bias, automate dependency management, and ensure high-quality data ingestion for downstream modeling and analysis.

Use Cases

  • Implementing ETL processes that require strict historical accuracy (PIT) to avoid lookahead bias in financial or time-series modeling.
  • Designing scalable data ingestion flows with built-in quality checks and schema validation using PyArrow to ensure data contract compliance.
  • Automating complex data dependency management and real-time notifications using Lineage DAGs and Pub/Sub patterns to trigger downstream tasks.
  • Configuring data freshness monitoring and update frequencies to ensure datasets meet SLA requirements and provide alerts for stale data.
  • Integrating Prefect orchestration for distributed task execution and error handling in large-scale data processing environments.
namedata-pipeline-patterns
descriptionFollow these patterns when implementing data pipelines, ETL, data ingestion, or data validation in OptAIC. Use for point-in-time (PIT) correctness, Arrow schemas, quality checks, and Prefect orchestration.

Data Pipeline Patterns

Guide for implementing data pipelines that integrate with OptAIC's orchestration and governance.

When to Use

Apply when:

  • Building PipelineDef implementations (ETL, Expression, Training)
  • Implementing data ingestion flows
  • Creating data quality validation
  • Setting up Arrow schemas for datasets
  • Integrating with Prefect orchestration

Pipeline Definition Types

Type Purpose Input Output
ETL External data ingestion API/files Dataset version
Expression DSL transformation Datasets Derived dataset
Training Model training Datasets Model artifact
Inference Model prediction Features + model Prediction dataset
Monitoring Quality/drift checks Datasets Metrics + alerts

Point-in-Time (PIT) Correctness

Critical rule: Always track knowledge_date (when data was known) separately from as_of_date (data's effective date).

# WRONG - lookahead bias
df = pd.read_sql("SELECT * FROM prices WHERE date = ?", [target_date])

# CORRECT - PIT query
df = pd.read_sql("""
    SELECT * FROM prices
    WHERE as_of_date <= ?
    AND knowledge_date <= ?
    ORDER BY knowledge_date DESC
""", [target_date, knowledge_cutoff])

See references/pit-patterns.md.

Arrow Schema Pattern

import pyarrow as pa

def price_schema() -> pa.Schema:
    return pa.schema([
        pa.field("date", pa.date32(), nullable=False),
        pa.field("symbol", pa.string(), nullable=False),
        pa.field("close", pa.float64(), nullable=False),
        pa.field("knowledge_date", pa.timestamp("us"), nullable=False),
    ])

Prefect Integration

from prefect import flow, task

@task
async def fetch_data(source: str, date: str) -> dict:
    pass

@task
async def validate_schema(data: dict, schema_ref: str) -> bool:
    pass

@flow
async def daily_refresh(dataset_id: UUID, date: str):
    raw = await fetch_data(...)
    if not await validate_schema(raw, schema_ref):
        raise ValidationError()
    await store_data(raw, dataset_id)
    await emit_activity("dataset.refreshed", ...)

See references/prefect-patterns.md.

Lineage DAG at Creation Time

CRITICAL: Lineage DAG is built when Instances are CREATED, NOT at execution time.

from libs.orchestration import LineageResolver

# At DatasetInstance creation:
async def create_dataset_instance(session, actor, payload):
    resolver = LineageResolver()

    # 1. Build lineage DAG from pipeline config
    dag = await resolver.build_dag_for_instance(session, instance.id, actor.tenant_id)

    # 2. Cache upstream IDs for fast execution checks
    if dag.has_dependencies:
        instance.upstream_resource_ids = dag.upstream_ids
        instance.upstream_status = {str(uid): "unknown" for uid in dag.upstream_ids}

        # 3. Create DatasetLineage + Subscription records
        await resolver.create_lineage_and_subscriptions(session, dag)

Pub/Sub Observer Pattern

Downstream datasets are notified when upstreams complete:

from libs.orchestration import LineageObserver, CentrifugoNotifier

async def on_run_completed(session, run):
    observer = LineageObserver()

    # Notify downstreams, get those now fully ready
    ready_ids = await observer.on_upstream_completed(
        session,
        upstream_id=run.dataset_instance_id,
        run_id=run.resource_id,
    )

    # Publish real-time notifications
    notifier = CentrifugoNotifier()
    for downstream_id in ready_ids:
        await notifier.notify_upstream_ready(downstream_id, upstream_id, True)

Fast Execution Check

Use cached status for execution checks (no lineage query):

from libs.orchestration import LineageResolver

resolver = LineageResolver()
all_ready = await resolver.check_all_upstreams_ready(session, instance_id)

if not all_ready and not force:
    raise UpstreamNotReadyError(...)

UpdateFrequency Configuration

Configure expected update frequency for freshness calculations:

from libs.orchestration import UpdateFrequency

# Daily data, 1 day grace period
frequency = UpdateFrequency(
    frequency="daily",
    grace_period_days=1,
)

# Business days only (skip weekends)
frequency = UpdateFrequency(
    frequency="daily",
    business_days_only=True,
    grace_period_days=1,
)

# Weekly on Monday
frequency = UpdateFrequency(
    frequency="weekly",
    day_of_week=0,  # 0=Monday
)

# Store in Instance config_json
config = {
    "update_frequency": {
        "frequency": "daily",
        "business_days_only": True,
        "grace_period_days": 1,
    }
}

See references/lineage-patterns.md.

Data Quality Checks

Standard checks to implement:

  • no_future_dates - Prevent lookahead
  • no_duplicates - Key uniqueness
  • coverage_check - Required dates/symbols
  • schema_conformance - Arrow schema match

See references/quality-checks.md.

Lazy Import Rule

Heavy deps must be lazy-loaded:

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    import pandas as pd
    import pyarrow as pa

Reference Files