Runtime Environments

Deploy once, run everywhere. One model for dev, QA, and production.

The Problem

Traditional approaches to multi-environment deployment require either:

  • Separate models per environment - duplication, drift, maintenance burden
  • Configuration files - error-prone, not type-safe, easy to deploy wrong config
  • Hard-coded environment logic - brittle, unmaintainable, scattered throughout code

None of these approaches scale. They create risk, slow down deployments, and make onboarding new environments painful.

The Solution: RuntimeEnvironments

RuntimeEnvironments (RTEs) use logical references in your model that are resolved at deployment time via EnvironmentMaps. One model, multiple environments, zero duplication.

Model Repository (Single Source of Truth)
Tag: V1.2.3-dev
RTE(dev)
Tag: V1.2.3-qa
RTE(qa)
Tag: V1.2.3-prod
RTE(prod)

How It Works

1. Define EnvironmentMaps

Teams define mappings from logical names to physical resources per environment:

team.add(EnvironmentMap(
    keyword="prod",
    dataContainers={
        frozenset(["customer_db"]): PostgresDatabase(
            "CustomerDB_Prod",
            hostPort=HostPortPair("prod-db.internal", 5432),
            databaseName="customer_production",
            productionStatus=ProductionStatus.PRODUCTION
        )
    },
    dtReleaseSelectors={
        "transformer_version": VersionPatternReleaseSelector(
            "V*.*.*-prod", ReleaseType.STABLE_ONLY
        )
    }
))

team.add(EnvironmentMap(
    keyword="dev",
    dataContainers={
        frozenset(["customer_db"]): PostgresDatabase(
            "CustomerDB_Dev",
            hostPort=HostPortPair("dev-db.internal", 5432),
            databaseName="customer_dev",
            productionStatus=ProductionStatus.NOT_PRODUCTION
        )
    },
    dtReleaseSelectors={
        "transformer_version": VersionPatternReleaseSelector(
            "V*.*.*-dev", ReleaseType.STABLE_ONLY
        )
    }
))

2. Use Logical References

Your model uses logical references - no environment-specific values:

Datastore(
    "CustomerData",
    capture_metadata=SQLSnapshotIngestion(
        EnvRefDataContainer("customer_db"),  # Logical reference
        CronTrigger("Hourly", "0 * * * *"),
        Credential("db_reader", CredentialType.USER_PASSWORD)
    ),
    datasets=[...]
)

DataTransformer(
    name="MaskCustomerPII",
    code=PythonCodeArtifact(
        VersionedRepository(
            GitHubRepository("myorg/transformers", "main"),
            EnvRefReleaseSelector("transformer_version")  # Logical reference
        )
    ),
    ...
)

3. Resolution at Deployment

When each RTE deploys, logical references resolve to environment-specific values:

Logical ReferenceProd ResolutionDev Resolution
EnvRefDataContainer("customer_db") prod-db.internal:5432 dev-db.internal:5432
EnvRefReleaseSelector("transformer_version") V1.0.0-prod V1.1.0-dev

Safety Features

The linter validates your model at PR time, preventing common mistakes:

Reference Validation

Every EnvRefDataContainer key must exist in the team's EnvironmentMaps. Missing references fail at lint time, not runtime.

Production Status

Production RTEs only reference production-status DataContainers. Dev/QA RTEs only reference non-production. No accidental cross-contamination.

Complete Coverage

Every RTE must have corresponding EnvironmentMaps for all teams it uses. Incomplete configurations are caught before deployment.

Deployment Workflow

  1. Develop - Teams develop and test with dev RTE (watches for -dev tags)
  2. Tag for QA - Tag model with V1.2.3-qa for QA environment testing
  3. QA validates - QA RTE picks up tag, deploys with qa EnvironmentMaps
  4. Tag for Prod - After validation, tag V1.2.3-prod for production
  5. Prod deploys - Prod RTE picks up tag, deploys with prod EnvironmentMaps

Each RTE's infrastructure updates independently within 5-15 minutes of tagging.

Benefits

Single Source of Truth

One model definition for all environments. No duplication, no drift.

Type-Safe Resolution

IDE autocomplete, compile-time validation, no string typos.

Independent Versions

Dev on V1.3.0, prod on V1.2.5. Each environment at its own pace.

Easy Onboarding

New environments just add EnvironmentMaps. No model changes required.

Real-World Impact

  • No environment-specific branches - single codebase, single PR workflow
  • No manual config edits - all configuration in type-safe Python
  • No accidental prod/dev mixing - validated at PR time
  • Faster deployments - tag and go, no manual coordination
Learn More About RTEs