Fluid Forge
Why Forge
Concepts
Get Started
  • Consume a Data Product
  • See it run
  • Demos
  • Local (DuckDB)
  • Source-Aligned (Postgres → DuckDB)
  • AI Forge + Data Models
  • MCP Output Port — Serve to AI Agents
  • GCP (BigQuery)
  • Snowflake Team Collaboration
  • Declarative Airflow
  • Orchestration Export
  • Jenkins CI/CD
  • Universal Pipeline
  • 11-Stage Production Pipeline
  • Catalog Forge End-to-End
CLI Reference
  • Agent Policy (concept)
  • MCP Output Port — Serve to Agents
  • MCP deep-dive
  • AI-assisted authoring
  • LLM providers & backends
  • Overview
  • Quickstart
  • Examples
  • Your own CI
  • Your own scaffolding
  • Custom validator
  • Apply hook
  • Reference
  • Overview
  • Architecture
  • GCP (BigQuery)
  • AWS (S3 + Athena)
  • Snowflake
  • Local (DuckDB)
  • Custom Providers
  • Roadmap
GitHub
Why Forge
Concepts
Get Started
  • Consume a Data Product
  • See it run
  • Demos
  • Local (DuckDB)
  • Source-Aligned (Postgres → DuckDB)
  • AI Forge + Data Models
  • MCP Output Port — Serve to AI Agents
  • GCP (BigQuery)
  • Snowflake Team Collaboration
  • Declarative Airflow
  • Orchestration Export
  • Jenkins CI/CD
  • Universal Pipeline
  • 11-Stage Production Pipeline
  • Catalog Forge End-to-End
CLI Reference
  • Agent Policy (concept)
  • MCP Output Port — Serve to Agents
  • MCP deep-dive
  • AI-assisted authoring
  • LLM providers & backends
  • Overview
  • Quickstart
  • Examples
  • Your own CI
  • Your own scaffolding
  • Custom validator
  • Apply hook
  • Reference
  • Overview
  • Architecture
  • GCP (BigQuery)
  • AWS (S3 + Athena)
  • Snowflake
  • Local (DuckDB)
  • Custom Providers
  • Roadmap
GitHub
  • Introduction

    • Home
    • Why Fluid Forge
    • Getting Started
    • Snowflake Quickstart
    • See it run
    • Forge Data Model
    • Vision & Roadmap
    • Playground
    • FAQ
  • Concepts

    • Concepts
    • Builds, Exposes, Bindings
    • What is a contract?
    • Quality, SLAs & Lineage
    • Governance & Policy
    • Agent Policy (LLM/AI governance)
    • Providers vs Platforms
    • Fluid Forge vs alternatives
  • Data Products

    • Consume a Data Product
    • Product Types — SDP, ADP, CDP
  • Walkthroughs

    • Walkthrough: Local Development
    • Source-Aligned: Postgres → DuckDB → Parquet
    • AI Forge And Data-Model Journeys
    • Walkthrough: MCP Output Port
    • Walkthrough: Deploy to Google Cloud Platform
    • Walkthrough: Snowflake Team Collaboration
    • Declarative Airflow DAG Generation - The FLUID Way
    • Generating Orchestration Code from Contracts
    • Jenkins CI/CD for FLUID Data Products
    • Universal Pipeline
    • The 11-Stage Pipeline
    • End-to-End Walkthrough: Catalog → Contract → Transformation
  • CLI Reference

    • CLI Reference
    • Core workflow

      • fluid init
      • fluid demo
      • fluid forge
      • fluid validate
      • fluid plan
      • fluid apply
      • fluid diff
      • fluid status
    • Build & ship

      • fluid bundle
      • fluid generate
      • fluid generate artifacts
      • fluid validate-artifacts
      • fluid verify-signature
      • fluid generate iac
      • fluid generate-airflow
      • fluid generate-pipeline
      • fluid viz-graph
      • fluid publish
      • fluid ship
      • fluid rollback
      • fluid schedule-sync
    • AI & Agents

      • fluid ai
      • fluid agents
      • fluid mcp
      • fluid memory
      • fluid stats
      • fluid skills
    • Quality & governance

      • fluid test
      • fluid verify
      • fluid contract-tests
      • fluid contract-validation
      • fluid policy
      • fluid policy check
      • fluid policy compile
      • fluid policy apply
    • Standards & interoperability

      • fluid odps
      • fluid odps-bitol
      • fluid odcs
      • fluid export
      • fluid export-odps
      • fluid exporters
      • fluid import
      • fluid market
      • fluid datamesh-manager
    • Project & workspace

      • fluid product-new
      • fluid product-add
      • fluid workspace
      • fluid contract
      • fluid split
      • fluid config
      • fluid providers
      • fluid plugins
      • fluid provider-init
      • fluid auth
      • fluid secrets
      • fluid ide
      • fluid scaffold-ci
      • fluid scaffold-composer
      • fluid scaffold-ide
      • fluid docs
      • fluid runs
      • fluid retention
      • fluid describe
      • fluid doctor
      • fluid roadmap
      • fluid version
    • Catalog adapters

      • Source Catalog Integration (V1.5)
      • Publishing to a Catalog — Overview
      • BigQuery Catalog
      • Snowflake Horizon Catalog
      • Databricks Unity Catalog
      • Google Dataplex Catalog
      • AWS Glue Data Catalog
      • DataHub Catalog
      • Data Mesh Manager Catalog
      • OpenMetadata Catalog
    • CLI by task

      • CLI by task
      • Add quality rules
      • Add agent governance
      • Debug a failed pipeline run
      • Switch clouds with one line
  • Recipes

    • Recipes
    • Recipe — add a quality rule
    • Recipe — switch clouds with one line
    • Recipe — tag PII in your schema
    • Write a contract that consumes another contract
    • Generate per-environment overlays
  • SDK & Plugins

    • SDK & Plugins
    • Quickstart — your first plugin
    • Examples

      • Runnable examples
      • Example: hello-scaffold — the minimal viable plugin
      • Example: gitlab-ci-scaffold — generate a complete CI project
      • Example: steward-validator — a custom governance rule
      • Example: prod-key-guard — apply-time invariant check
    • Journeys

      • Journeys
      • Your own CI/CD

        • You have your own CI/CD setup, no problem
        • GitLab CI — the bundle template
        • GitHub Actions — the bundle template
        • Jenkins — the bundle template
        • CircleCI — the bundle template
      • You have a strict project layout, no problem
      • You have governance rules, no problem
      • You want a check at apply time, no problem
    • Reference

      • Reference
      • Roles reference
      • Entry points reference
      • Trust model
      • Packaging
      • Companion packages
  • Providers

    • Providers
    • Provider Architecture
    • GCP Provider
    • AWS Provider
    • Snowflake Provider
    • Local Provider
    • Creating Custom Providers
    • Provider Roadmap
  • AI & Agents

    • MCP Server
    • Built-in And Custom Forge Guidance
    • Forge Discovery Guide
    • Forge Memory Guide
    • Authoring Forge Tools
    • Guided fluid forge UX
    • LLM Providers
    • LiteLLM Backend
    • Capability Warnings
    • Cost Tracking
    • FLUID Forge Contract GPT Packet
    • Agentic Primitives
  • Operate & Deploy

    • Airflow Integration
    • Blueprints
    • Source-Aligned Acquisition
  • Govern & Secure

    • Governance, Compliance & the Business Case
    • Governance & Compliance
    • Network Safety
    • Credential Resolver — Security Model
  • Configuration & Reference

    • Environment Variables
    • Typed Errors
    • Typed CLI Errors
    • API Stability — fluid_build.api
  • Architecture & Releases

    • V1.5 Catalog Integration — Architecture Deep-Dive
    • V1.5 + V2 Hardening — Release Notes
  • Project

    • Contributing to Fluid Forge
    • Fluid Forge Docs Baseline: CLI 0.9.0
    • Fluid Forge Docs Baseline: CLI 0.8.11
    • Fluid Forge Docs Baseline: CLI 0.8.10
    • Fluid Forge Docs Baseline: CLI 0.8.9
    • Fluid Forge Docs Baseline: CLI 0.8.8
    • Fluid Forge Docs Baseline: CLI 0.8.7
    • Fluid Forge Docs Baseline: CLI 0.8.6
    • Fluid Forge Docs Baseline: CLI 0.8.5
    • Fluid Forge Docs Baseline: CLI 0.8.4
    • Fluid Forge Docs Baseline: CLI 0.8.3
    • Fluid Forge Docs Baseline: CLI 0.8.0
    • Fluid Forge Docs Baseline: CLI 0.7.11
    • Fluid Forge Docs Baseline: CLI 0.7.9
    • Fluid Forge v0.7.1 - Multi-Provider Export Release

AWS Provider

Deploy data products to Amazon Web Services — S3, Glue, Athena — using the same contract and CLI commands as every other provider.

Status: ✅ Production
Docs Baseline: CLI 0.10.0
Tested Services: S3, Glue Data Catalog, Athena, IAM

Why it matters Run the same contract on AWS (S3 + Athena / Glue) with no AWS-specific rewrite. Set binding.platform: aws and Forge compiles the contract to Glue / Athena DDL and OpenTofu — the contract itself doesn't change.

AWS quickstart — S3 + Glue + Athena in 30 seconds
Same Customer 360 contract as the local quickstart, with binding.platform swapped to aws. S3 bucket provisioned, Glue catalog auto-created, Athena made queryable — all from one fluid apply.

Compatibility note

Examples on this page use the current fluidVersion: 0.7.5 shape. Orchestration guidance now prefers fluid generate schedule --scheduler airflow over the older fluid generate-airflow.


Overview

The AWS provider turns a FLUID contract into real cloud infrastructure:

  • ✅ Plan & Apply — S3 buckets, Glue databases/tables, Athena workgroups
  • ✅ IAM Policy Compilation — fluid policy-compile generates S3, Glue, and Athena IAM bindings from accessPolicy grants
  • ✅ Sovereignty Validation — Region allow/deny lists enforced before deployment
  • ✅ Orchestration Generation — prefer fluid generate schedule --scheduler airflow for current docs and automation
  • ✅ Lake Formation Governance — principal grants, column-level grants, LF-tags (TBAC), row filters, and location registration via binding.governance.lakeFormation
  • ✅ Universal Pipeline — Same Jenkinsfile as GCP and Snowflake — zero provider logic

Working Example: Bitcoin Price Tracker

This is a production-tested example that runs end-to-end in Jenkins CI.

Contract

fluidVersion: "0.7.4"
kind: DataProduct
id: crypto.market_data.bitcoin_prices_aws_v1
name: Bitcoin Price Tracker (AWS Athena)
description: >
  Real-time Bitcoin price data stored in AWS Athena with S3 backend,
  with comprehensive governance
domain: Market Data

tags:
  - crypto
  - market-data
  - real-time
  - governed
  - gdpr-compliant

labels:
  team: data-engineering
  cost-center: analytics
  business_criticality: "high"
  compliance_gdpr: "true"
  platform: "aws"

metadata:
  layer: Gold
  owner:
    team: data-engineering
    email: data-eng@company.com

# ── Data Sovereignty ──────────────────────────────────────────
sovereignty:
  jurisdiction: "EU"
  dataResidency: true
  allowedRegions:
    - eu-central-1       # AWS Frankfurt (GDPR compliant)
    - eu-west-1          # AWS Ireland
  deniedRegions:
    - us-east-1
    - us-west-2
  crossBorderTransfer: false
  transferMechanisms:
    - SCCs
  regulatoryFramework:
    - GDPR
    - SOC2
  enforcementMode: advisory
  validationRequired: true

# ── Access Policy: AWS IAM Principals ─────────────────────────
accessPolicy:
  grants:
    - principal: "role:data-analyst"
      permissions: [read, select, query]

    - principal: "role:finance-team"
      permissions: [read, select]

    - principal: "role:trading-desk"
      permissions: [read, select, query]

    - principal: "role:data-engineer"
      permissions: [write, insert, update, delete, create]

    - principal: "role:pipeline-service"
      permissions: [read, write, insert]

# ── Expose: Athena Table ──────────────────────────────────────
exposes:
  - exposeId: bitcoin_prices_table
    title: Bitcoin Real-time Price Feed
    version: "1.0.0"
    kind: table

    binding:
      platform: aws
      format: parquet
      location:
        database: crypto_data
        table: bitcoin_prices
        bucket: "{{ env.S3_BUCKET }}"
        path: data/bitcoin/prices/
        region: "{{ env.AWS_REGION }}"

    # Governance policies
    policy:
      classification: Internal
      authn: iam
      authz:
        readers:
          - role:data-analyst
          - role:finance-team
          - role:trading-desk
          - role:pipeline-service
        writers:
          - role:data-engineer
          - role:pipeline-service
        columnRestrictions:
          - principal: "role:intern"
            columns: [market_cap_usd, volume_24h_usd]
            access: deny
      # NOTE: on AWS, policy.privacy.masking / rowLevelPolicy are declarative
      # metadata only — they emit no AWS infrastructure. Use
      # binding.governance.lakeFormation for enforced row/column governance.
      privacy:
        masking:
          - column: "ingestion_timestamp"
            strategy: "hash"
            params:
              algorithm: "SHA256"
        rowLevelPolicy:
          expression: >
            price_timestamp >= DATE_ADD('day', -30, CURRENT_TIMESTAMP)

    # Schema contract
    contract:
      schema:
        - name: price_timestamp
          type: timestamp
          required: true
          description: UTC timestamp when price was recorded
          sensitivity: cleartext
          semanticType: "timestamp"

        - name: price_usd
          type: decimal(18,2)
          required: true
          description: Bitcoin price in USD
          sensitivity: cleartext
          semanticType: "currency"

        - name: price_eur
          type: decimal(18,2)
          required: false
          description: Bitcoin price in EUR

        - name: price_gbp
          type: decimal(18,2)
          required: false
          description: Bitcoin price in GBP

        - name: market_cap_usd
          type: decimal(20,2)
          required: false
          description: Total market capitalization in USD
          sensitivity: internal

        - name: volume_24h_usd
          type: decimal(20,2)
          required: false
          description: 24-hour trading volume in USD
          sensitivity: internal

        - name: price_change_24h_pct
          type: decimal(10,4)
          required: false
          description: 24-hour price change percentage

        - name: last_updated
          type: timestamp
          required: false
          description: Timestamp from CoinGecko API

        - name: ingestion_timestamp
          type: timestamp
          required: true
          description: When data was ingested into our system

# ── Build: API Ingestion ──────────────────────────────────────
builds:
  - id: bitcoin_price_ingestion
    description: Fetch Bitcoin prices from CoinGecko API
    pattern: hybrid-reference
    engine: python
    repository: ./runtime
    properties:
      model: ingest
    execution:
      trigger:
        type: manual
        iterations: 1
        delaySeconds: 3
      runtime:
        image: python:3.11-slim
        dependencies: [boto3, requests, pyarrow]
        env: [AWS_REGION, S3_BUCKET, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY]
      retries:
        count: 3
        backoff: exponential
    outputs:
      - bitcoin_prices_table

Key Schema Patterns

The binding schema uses three fields to identify platform resources:

FieldPurposeAWS Values
binding.platformCloud provideraws
binding.formatStorage formatparquet, s3_file, csv, json
binding.locationResource coordinatesbucket, path, region, database, table

This is identical to GCP (platform: gcp, format: bigquery_table) and Snowflake (platform: snowflake, format: snowflake_table).

CLI Commands

Every command is identical across providers. No --provider flag needed — the CLI reads the provider from the contract's binding.platform field.

# Validate contract against the bundled JSON schema
fluid validate contract.fluid.yaml --verbose

# Generate execution plan
fluid plan contract.fluid.yaml --env dev --out plans/plan-dev.json

# Deploy S3 bucket, Glue DB, Athena table
fluid apply contract.fluid.yaml --env dev --yes

# Compile IAM policies from accessPolicy grants
fluid policy-compile contract.fluid.yaml --env dev --out runtime/policy/bindings.json

# Apply IAM bindings (dry-run or enforce)
fluid policy-apply runtime/policy/bindings.json --mode check
fluid policy-apply runtime/policy/bindings.json --mode enforce

# Run the ingest script
fluid apply contract.fluid.yaml --mode amend-and-build

# Generate Airflow DAG
fluid generate-airflow contract.fluid.yaml --output airflow-dags/bitcoin_aws.py

# Export standards
fluid odps export contract.fluid.yaml --output standards/product.odps.json
fluid odcs export contract.fluid.yaml --output standards/product.odcs.yaml

IAM Policy Compilation

fluid policy-compile reads accessPolicy.grants from the contract and generates AWS IAM permission bindings:

{
  "provider": "aws",
  "bindings": [
    {
      "role": "role:data-analyst",
      "resource": "bitcoin_prices_table",
      "permissions": [
        "s3:GetObject",
        "s3:ListBucket",
        "glue:GetTable",
        "glue:GetDatabase",
        "athena:StartQueryExecution",
        "athena:GetQueryExecution",
        "athena:GetQueryResults"
      ]
    },
    {
      "role": "role:data-engineer",
      "resource": "bitcoin_prices_table",
      "permissions": [
        "s3:PutObject",
        "s3:DeleteObject",
        "glue:CreateTable",
        "glue:UpdateTable",
        "glue:DeleteTable"
      ]
    }
  ]
}

The permission mapping:

Contract PermissionAWS IAM Actions
read, select, querys3:GetObject, s3:ListBucket, glue:GetTable, glue:GetDatabase, athena:StartQueryExecution, athena:GetQueryResults
write, insert, update, deletes3:PutObject, s3:DeleteObject, glue:CreateTable, glue:UpdateTable, glue:DeleteTable

Credentials Setup

Jenkins CI (Recommended)

Create a Jenkins Secret File credential containing your AWS env vars:

# File contents (plain key=value, no 'export' prefix)
AWS_ACCESS_KEY_ID=AKIAxxxxxxxxxxxx
AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
AWS_REGION=eu-central-1
S3_BUCKET=my-fluid-data-bucket

The Universal Pipeline auto-detects this format and sources it into every stage. No provider-specific credential logic.

Local Development

# Option 1: AWS CLI profile
aws configure --profile fluid-dev

# Option 2: .env file (same format as Jenkins)
cat > .env << 'EOF'
AWS_ACCESS_KEY_ID=AKIAxxxxxxxxxxxx
AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
AWS_REGION=eu-central-1
S3_BUCKET=my-fluid-data-bucket
EOF

# Source and run
set -a; . .env; set +a
fluid apply contract.fluid.yaml --env dev --yes

Infrastructure Created

When you run fluid apply on an AWS contract, the provider creates:

ResourceDetails
S3 Buckets3://{S3_BUCKET}/data/bitcoin/prices/ — Parquet data storage
Glue Databasecrypto_data — Data Catalog database
Glue Tablebitcoin_prices — External table pointing to S3
Athena WorkgroupQuery engine configured for the region

What the Pipeline Produces

After a successful run, the pipeline writes real data:

s3://my-fluid-bucket/data/bitcoin/prices/
  └── bitcoin_prices_20250130_143052.parquet   ← BTC at $104,809

Queryable immediately via Athena:

SELECT price_timestamp, price_usd, price_eur, market_cap_usd
FROM crypto_data.bitcoin_prices
ORDER BY price_timestamp DESC
LIMIT 5;

Governance Features

Data Sovereignty

The sovereignty block enforces region restrictions before any infrastructure is deployed:

sovereignty:
  jurisdiction: "EU"
  allowedRegions: [eu-central-1, eu-west-1]
  deniedRegions: [us-east-1, us-west-2]
  crossBorderTransfer: false
  regulatoryFramework: [GDPR, SOC2]
  enforcementMode: advisory  # or strict (blocks deployment)

Lake Formation — the AWS governance surface

On AWS, row- and column-level governance is implemented through Lake Formation, declared under binding.governance.lakeFormation (with account-level admins/tag definitions under the top-level governance.lakeFormation block). On the OpenTofu apply path Forge emits the full Lake Formation surface:

Contract fieldAWS resource emitted
governance.lakeFormation.adminsaws_lakeformation_data_lake_settings
governance.lakeFormation.tagDefinitionsaws_lakeformation_lf_tag
binding.governance.lakeFormation.registerLocationaws_lakeformation_resource
binding.governance.lakeFormation.grantsaws_lakeformation_permissions (column-scoped via table_with_columns)
binding.governance.lakeFormation.tagsaws_lakeformation_resource_lf_tags (TBAC)
binding.governance.lakeFormation.rowFilteraws_lakeformation_data_cells_filter (row + optional column projection)
exposes:
  - exposeId: bitcoin_prices_table
    binding:
      platform: aws
      format: parquet
      governance:
        lakeFormation:
          registerLocation: true
          grants:
            - principal: "arn:aws:iam::123456789012:role/data-analyst"
              permissions: [SELECT]
              columns: [price_timestamp, price_usd]   # column-level grant
          rowFilter:
            name: recent_only
            expression: "price_timestamp >= DATE_ADD('day', -30, CURRENT_TIMESTAMP)"

Lake Formation column grants and data-cells-filter column projection control access to columns. Lake Formation does not provide dynamic data-value masking, and there is no AWS data-masking primitive in this layer.

policy.privacy.masking / rowLevelPolicy are declarative-only on AWS

The policy.privacy.masking, policy.privacy.rowLevelPolicy, and policy.authz.columnRestrictions fields are valid in the schema, but no AWS provider or IaC code reads them — they emit no AWS infrastructure. Use binding.governance.lakeFormation (above) for AWS row/column governance. The policy.privacy block records intent as contract metadata only.

CI/CD Pipeline

The AWS example uses the exact same Jenkinsfile as GCP and Snowflake — the Universal Pipeline. Key stages:

StageCommandWhat Happens
Validatefluid validateContract checked against the bundled schema
Exportfluid odps export / fluid odcs exportStandards files generated
Compile IAMfluid policy-compileaccessPolicy → IAM bindings JSON
Planfluid planExecution plan generated
Applyfluid applyS3 bucket + Glue DB/table created
Apply IAMfluid policy-applyIAM bindings enforced
Executefluid apply --mode amend-and-buildingest.py runs, writes Parquet to S3
Airflow DAGfluid generate-airflowProduction DAG generated

See Also

  • Universal Pipeline — Same Jenkinsfile for every provider
  • Snowflake Provider — Snowflake Data Cloud integration
  • GCP Provider — Google Cloud Platform integration
  • CLI Reference — Full command documentation
Edit this page on GitHub
Last Updated: 6/27/26, 4:58 PM
Contributors: Jeff Watson, jeffwatson-ai, fas89, Claude Opus 4.7 (1M context)
Prev
GCP Provider
Next
Snowflake Provider