> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ubiquex.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Third-Party Provider — Datadog

> Use any Pulumi-compatible provider with automatic schema sync on first validate.

ubx ships with schemas cached for the major cloud providers — AWS, GCP, Azure, Kubernetes. But Pulumi's provider ecosystem is vast: Datadog, Cloudflare, PagerDuty, GitHub, Snowflake, and hundreds more. Any provider published to the Pulumi Registry works in ubx with one addition: a `provider` block that declares the `source` (the registry namespace and provider name) and the version. On first `ubx validate`, ubx fetches the provider's schema from the Pulumi Registry, caches it locally, and uses it for type-checking. This is a one-time network request — subsequent validates use the cache and work offline. The provider schema fetch is categorically different from cloud credentials: it's a public registry call, not a cloud API call, and it never touches your actual Datadog account.

## What you'll learn

* How to use any Pulumi Registry provider with `source = "publisher/provider"`
* The one-time schema auto-sync on first validate
* How third-party provider usage differs from cloud credential requirements

***

## Why this matters

<Info>
  Managing Datadog monitors, Cloudflare DNS records, or GitHub repositories in the same `.iac` files as your AWS infrastructure means your full platform configuration lives in one place — the same language, the same type system, the same `ubx apply`. No separate Terraform configs, no separate tooling.
</Info>

***

## The source code

<CodeGroup>
  ```hcl main.iac theme={"theme":"css-variables"}
  unit "datadog_monitor" "api_latency" {
    name    = "myapp-${input.env}: API p99 latency"
    type    = "metric alert"
    message = "High API p99 latency detected. Notifying @slack-platform."
    query   = "avg(last_5m):avg:trace.express.request{env:${input.env}} > 0.5"
  }

  unit "datadog_monitor" "error_rate" {
    name    = "myapp-${input.env}: Error rate"
    type    = "metric alert"
    message = "Error rate above threshold. Notifying @pagerduty."
    query   = "avg(last_5m):sum:errors{env:${input.env}}.as_rate() > 0.01"
  }
  ```

  ```hcl inputs.iac theme={"theme":"css-variables"}
  input "env" {
    type    = "string"
    default = "prod"
  }
  ```

  ```hcl ubx.iac theme={"theme":"css-variables"}
  ubx {
    name    = "third-party-provider-datadog"
    runtime = "typescript"
    stacks  = ["dev", "staging", "prod"]
  }

  # source = "pulumi/datadog" tells ubx to fetch the schema from
  # the Pulumi Registry under the pulumi/ publisher namespace.
  # On first ubx validate, the schema is auto-fetched and cached.
  # Subsequent validates use the cache — no network required.
  provider "datadog" {
    source  = "pulumi/datadog"
    version = "~> 5.0"
  }

  backend "s3" {
    bucket = "my-ubx-state"
    region = "us-east-1"
    key    = "${stack}/datadog-monitors.tfstate"
  }
  ```
</CodeGroup>

***

## How it works

<Steps>
  <Step title="ubx detects an uncached provider schema">
    When `ubx validate` encounters a `unit "datadog_monitor"` block and the Datadog provider schema isn't cached at `~/.ubx/schemas/datadog.json`, it checks the `provider` block for `source = "pulumi/datadog"` and fetches the schema from `https://api.pulumi.com/registry/packages/datadog`.
  </Step>

  <Step title="The schema is cached locally after the first fetch">
    The downloaded schema is written to `~/.ubx/schemas/datadog@5.x.json`. All subsequent `ubx validate` calls use the cache — no network request, no Datadog credentials, no Pulumi account needed. Run `ubx schema sync datadog` to explicitly refresh the cache.
  </Step>

  <Step title="Type checking works identically to built-in providers">
    Once cached, the Datadog schema is used exactly like the AWS schema: unknown attributes produce warnings, missing required attributes produce errors, and attribute types are checked. The provider being third-party is invisible to the rest of the compile pipeline.
  </Step>
</Steps>

***

## What ubx generates

<CodeGroup>
  ```typescript index.ts theme={"theme":"css-variables"}
  // Generated by ubx — do not edit
  import * as pulumi from "@pulumi/pulumi";
  import * as datadog from "@pulumi/datadog";

  const config = new pulumi.Config();
  const env = config.get("env") || "prod";

  const apiLatency = new datadog.Monitor("api_latency", {
      name: `myapp-${env}: API p99 latency`,
      type: "metric alert",
      message: "High API p99 latency detected. Notifying @slack-platform.",
      query: `avg(last_5m):avg:trace.express.request{env:${env}} > 0.5`,
  });

  const errorRate = new datadog.Monitor("error_rate", {
      name: `myapp-${env}: Error rate`,
      type: "metric alert",
      message: "Error rate above threshold. Notifying @pagerduty.",
      query: `avg(last_5m):sum:errors{env:${env}}.as_rate() > 0.01`,
  });
  ```

  ```python __main__.py theme={"theme":"css-variables"}
  # Generated by ubx — do not edit
  import pulumi
  import pulumi_datadog as datadog

  config = pulumi.Config()
  env = config.get("env") or "prod"

  api_latency = datadog.Monitor("api_latency",
      name=f"myapp-{env}: API p99 latency",
      type="metric alert",
      message="High API p99 latency detected. Notifying @slack-platform.",
      query=f"avg(last_5m):avg:trace.express.request{{env:{env}}} > 0.5",
  )

  error_rate = datadog.Monitor("error_rate",
      name=f"myapp-{env}: Error rate",
      type="metric alert",
      message="Error rate above threshold. Notifying @pagerduty.",
      query=f"avg(last_5m):sum:errors{{env:{env}}}.as_rate() > 0.01",
  )
  ```

  ```go main.go theme={"theme":"css-variables"}
  // Generated by ubx — do not edit
  package main

  import (
      "github.com/pulumi/pulumi-datadog/sdk/v4/go/datadog"
      "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
      "github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
  )

  func main() {
      pulumi.Run(func(ctx *pulumi.Context) error {
          cfg := config.New(ctx, "")
          env := cfg.Get("env")
          if env == "" { env = "prod" }

          _, err := datadog.NewMonitor(ctx, "api_latency", &datadog.MonitorArgs{
              Name:    pulumi.Sprintf("myapp-%s: API p99 latency", env),
              Type:    pulumi.String("metric alert"),
              Message: pulumi.String("High API p99 latency detected. Notifying @slack-platform."),
              Query:   pulumi.Sprintf("avg(last_5m):avg:trace.express.request{env:%s} > 0.5", env),
          })
          if err != nil { return err }

          _, err = datadog.NewMonitor(ctx, "error_rate", &datadog.MonitorArgs{
              Name:    pulumi.Sprintf("myapp-%s: Error rate", env),
              Type:    pulumi.String("metric alert"),
              Message: pulumi.String("Error rate above threshold. Notifying @pagerduty."),
              Query:   pulumi.Sprintf("avg(last_5m):sum:errors{env:%s}.as_rate() > 0.01", env),
          })
          return err
      })
  }
  ```
</CodeGroup>

***

## Common mistakes

<Warning>
  The schema auto-sync requires network access to `api.pulumi.com`. If you're in an air-gapped environment or have network restrictions, run `ubx schema sync datadog --no-registry` and provide the schema file manually. Use `ubx validate --no-network` to skip the auto-sync and validate with the cached schema only (produces warnings if the schema isn't cached yet).
</Warning>

<Tip>
  `ubx apply` for Datadog resources requires Datadog API credentials — set `DATADOG_API_KEY` and `DATADOG_APP_KEY` environment variables before running. These are cloud credentials, not schema credentials — the schema fetch works without them.
</Tip>

***

## Run it

```bash theme={"theme":"css-variables"}
# First validate fetches the Datadog schema (requires network to api.pulumi.com)
ubx validate
# Subsequent validates use the cache (offline-capable)
ubx validate --no-network
# Apply requires Datadog API credentials
DATADOG_API_KEY=xxx DATADOG_APP_KEY=yyy ubx apply
```

***

## What you learned

<Check>Any Pulumi Registry provider works in ubx with `source = "publisher/provider"` on a `provider` block</Check>
<Check>The schema is auto-fetched from the Pulumi Registry on first validate and cached locally</Check>
<Check>Schema fetching is a public registry call — distinct from cloud credentials needed for apply</Check>

***

## Next steps

<CardGroup cols={2}>
  <Card title="Backend S3 state" href="/v1/tutorials/39-backend-s3-state">
    Store Pulumi state in S3 with per-stack isolation
  </Card>

  <Card title="provider block reference" href="/v1/language/provider">
    Full provider block syntax and all source formats
  </Card>
</CardGroup>

***

<Info>
  Full runnable example: [github.com/ubiquex/ubx-examples/38-third-party-provider-datadog](https://github.com/ubiquex/ubx-examples/tree/main/38-third-party-provider-datadog)
</Info>
