How to set up Datadog monitoring for a Webflow Cloud app

Learn how to set up Datadog monitoring on a Webflow Cloud app.

How to set up Datadog monitoring for a Webflow Cloud app

Ismail Ajagbe
Technical Author
View author profile
Ismail Ajagbe
Technical Author
View author profile
Table of contents

Achieve complete visibility into your Webflow Cloud app without needing infrastructure-level access. Send metrics directly from your Route Handlers.

Webflow Cloud runs your app on Cloudflare's runtime, but Webflow owns the Cloudflare account. You have no host to install anything on and no infrastructure console to enable anything in. What you do have is code that can make an outbound request, and that's enough.

This guide outlines the complete process for instrumenting your Webflow Cloud application with Datadog. You will learn to define a monitoring strategy that works within platform constraints and submit custom metrics directly in your Route Handlers without blocking requests.

What do you need to set up Datadog monitoring in Webflow Cloud?

You need a Datadog account, an API key, the correct site for that account, and a Webflow Cloud app you can edit. People often get the site wrong.

Here’s the full list before you start:

  • A Datadog account, with permission to create API keys under Organization settings
  • Your Datadog site, which is the region your account lives in and determines every URL you will call
  • A Webflow Cloud app on Next.js 15 or higher, with Node.js 22 or later locally
  • A clear idea of the two or three numbers that would actually tell you something is wrong

That last item is not padding. Datadog bills custom metrics by unique combinations of name and tags, so measuring everything has a price attached, and the discipline of choosing is part of the setup, not a refinement to make later.

Once the account exists, everything hinges on getting the site right, because the wrong site fails in a way that looks like nothing at all.

5 steps to set up Datadog monitoring for a Webflow Cloud app

The build includes an API key, a function that posts a metric, a way to send it without delaying your response, a tagging decision, and the monitor that makes it all useful.

The order matters because the fourth step is much harder to change once metrics are flowing under names you have already built dashboards on.

1. Create an API key and confirm your Datadog site

In Datadog, open Organization settings, then API keys, and create one. API key values stay viewable there so that you can return to it. Do not confuse this with an application key, which is a different credential and which newer organizations show only once at creation.

Then find your site, which matters more than the key. Datadog runs nine independent sites, split by region and by compliance regime, and the documentation states plainly that you cannot share data across them.

Each site has its own API hostname, so an account on the EU site that posts to the US endpoint isn't sending data to the wrong dashboard; it is sending data to an organization that doesn't include you.

Datadog also lists the site at the top of My Preferences, though its docs describe that specifically for organizations on a custom domain, so do not treat a space there as an answer.

Store both values as environment variables on the Webflow Cloud environment rather than in the repository. Webflow Cloud makes environment variables available to both the build and the deployed application at runtime, and redacts secret values from build logs.

You finish this step with a key and a site string you have read rather than assumed.

2. Write the function that sends a metric

Metrics go to the series endpoint on your site's API host. The whole integration is one function, and it is worth writing yourself rather than reaching for a library that expects a runtime you don't have.

<><intro snippet>:

// lib/datadog.ts
type Point = {
  metric: string
  value: number
  tags: string[]
  // 3 = gauge (a measurement, averaged), 1 = count (summed).
  // A duration is a gauge. Sending it as a count graphs two
  // 200ms requests as 400.
  type?: 1 | 3
}

export async function sendMetric({ metric, value, tags, type = 3 }: Point) {
  // Seconds, not milliseconds. Datadog rejects points more than
  // 10 minutes ahead or an hour behind, and Date.now() lands
  // roughly 55,000 years in the future.
  const now = Math.floor(Date.now() / 1000)

  // Read the key here rather than at module scope: the adapter
  // populates process.env on the first request, not at startup.
  const DD_API_KEY = process.env.DD_API_KEY

  const site = process.env.DD_SITE ?? 'datadoghq.com'

  const res = await fetch(`https://api.${site}/api/v2/series`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'DD-API-KEY': DD_API_KEY!,
    },
    body: JSON.stringify({
      series: [
        {
          metric,
          type,
          points: [{ timestamp: now, value }],
          tags,
        },
      ],
    }),
  })

  // A bad key returns 403 with a body, not a thrown error.
  if (!res.ok) {
    console.error('datadog rejected the metric', res.status, await res.text())
  }
}

Three details in there earn their place. The timestamp is in seconds rather than milliseconds, which is the single most common reason a first metric never appears.

The default type is gauge, because most of what you will measure is a level rather than a tally, and a duration sent as a count is summed instead of averaged. And the error branch logs rather than throws, because a rejected metric should never take down the request it was measuring.

If you send a count, Datadog's API also requires an interval in seconds, so add that field rather than leaving the rate ambiguous.

Also note that Datadog does not rate-limit metric or log submission, so the constraint on how much you send is billing, not throttling. There is still a payload ceiling of 500 kilobytes per request, which matters only if you start batching.

You finish this step with a function you can call from anywhere in the app.

3. Send it without slowing your own response

Calling that function with await inside a Route Handler adds a round trip to Datadog to every request your users wait for. On a checkout endpoint, that is a real cost paid by real customers to record a number nobody reads in real time.

Use the Cloudflare context's waitUntil instead, which keeps the request alive long enough to finish the send after the response has gone out:

// app/api/checkout/route.ts
import { getCloudflareContext } from '@opennextjs/cloudflare'
import { sendMetric } from '@/lib/datadog'

export async function POST(request: Request) {
  const started = Date.now()
  const result = await processCheckout(request)

  const { ctx } = getCloudflareContext()

  // Hand the send to waitUntil so the metric leaves after the
  // response does. Awaiting it here would add Datadog's round
  // trip to every checkout your customers wait through.
  ctx.waitUntil(
    sendMetric({
      metric: 'app.checkout.duration',
      value: Date.now() - started,
      tags: [
        `env:${process.env.WEBFLOW_ENV ?? 'production'}`,
        `status:${result.ok ? 'ok' : 'failed'}`,
      ],
    }),
  )

  return Response.json(result)
}

This matters more on Webflow Cloud than it would elsewhere, because the platform allows only six simultaneous outgoing requests per invocation and enforces a twenty-second request timeout. A blocking monitoring call competes with the calls your feature actually needs.

After this step, you can hit the endpoint and watch the metric appear in the Metrics Explorer.

4. Choose tags deliberately, because tags are the bill

Stop before adding tags, because this is where monitoring setups quietly become expensive. Datadog defines a custom metric as a unique combination of the metric name and its tag values, which means the count you are billed on is multiplicative rather than additive.

A metric tagged with environment and status has a handful of combinations. The same metric, tagged additionally with user ID, has as many combinations as you have users. Request IDs, session IDs, full URL paths containing IDs and raw error messages all behave the same way, and each of them turns one metric into thousands.

The rule that holds up is to tag with things you would group by, not things you would look up. Environment, route name, status class and region are groupings. A user ID is a lookup, and it belongs in a log line where it costs you nothing, not in a metric tag where it multiplies.

If you want per-user detail, send it as a log and keep the metric coarse.

You finish this step with a tag list you could justify on an invoice.

5. Build the monitor that actually tells you

A metric arriving in Datadog is not monitoring. Nothing has been monitored until something reaches you when the number moves.

In Datadog, open Monitors, then New Monitor, choose Metric, and select the metric you just sent. Set a threshold you would genuinely want waking you, and send notifications somewhere you read them rather than somewhere you have muted.

Give particular attention to the no data setting. An app that has stopped serving requests entirely sends no metrics, so a threshold monitor watching for a high error count sees nothing and stays quiet.

That is the outage you most wanted to hear about, and it is the one a naive threshold is silent for. Configure the monitor to alert on missing data as well as on bad data.

Finish this step with an alert you have triggered on purpose at least once; that is the only way to know the notification path works.

What causes Datadog monitoring to fail on Webflow Cloud?

Monitoring fails in a particularly unhelpful way: the thing that is supposed to tell you something is wrong is itself wrong, and it reports its own failure to nobody.

Four account for nearly everything, and the first costs the most time because it produces no error anywhere.

Metrics never appear in Datadog

Cause: Usually the wrong Datadog site. These fail in two different ways, and it is worth knowing which you have. A key from one site posted to another host is rejected outright with a 403, which the logger from step 2 will show you.

A key that is valid for the host you posted to, but not the site you are viewing in the browser, succeeds silently and puts your data in an organization you are not viewing.

Fix: Log the response status from the intake call once. A 403 means the key and the host disagree. A 202 means Datadog accepted the payload, so the data exists somewhere, and the next question is whether you are looking at the site you sent it to.

Check the hostname you are logged into against the DD_SITE value the app is deployed with, since the sites are wholly independent and cannot share data.

The metric is accepted but never shows on a graph

Cause: The timestamp is in milliseconds rather than seconds. Date.now() returns milliseconds, which places the point roughly 55,000 years ahead. Datadog documents a hard acceptance window of no more than ten minutes into the future or one hour into the past, so the point isn't stored somewhere unhelpful; it is discarded.

Fix: Divide by 1000 and floor it, as the helper in step 2 does. Don't look for the missing points afterward by widening the graph window; they were never written, so the only thing to check is that new points land once the conversion is right.

This one is worth catching with a deliberate test rather than by observation. Send a single metric by hand, find it on a graph, and only then wire it into a Route Handler. A timestamp bug found on the first point costs a minute; found after a week of traffic, it means a week of data you cannot chart.

Responses get slower after adding monitoring

Cause: The intake call is being awaited inside the request rather than handed to waitUntil. Every user now waits for Datadog before they see your response, and on a slow day for Datadog they wait for a timeout.

Fix: Move the send into ctx.waitUntil as above, so the response leaves first and the metric follows. Also remember that Webflow Cloud caps simultaneous outgoing requests at six per invocation, so a handler that already fans out to several services and then adds a blocking monitoring call can end up queuing against its own instrumentation.

The failure worth anticipating is when Datadog itself is slow. An awaited call ties your response time to a third party's availability, which means an incident at your monitoring vendor becomes an incident on your site. Handing the send to waitUntil removes that coupling entirely.

The Datadog bill grows faster than the traffic

Cause: High cardinality tags. A metric tagged with anything unique per request or per user is not one custom metric; it is one per distinct value, and the count compounds quietly because nothing about the code looks different.

Fix: Check the usage details page, which lists the account's top custom metrics, and find the metric whose name you recognize but whose volume you don't. Then strip the offending tag and move that detail into a log line, where the same information costs you nothing per distinct value.

Do this early. Once dashboards and monitors are built on a tag, removing it means rebuilding both, and the pressure at that point is to keep paying rather than to unpick it. The cheapest moment to fix cardinality is before anyone depends on the shape of the data.

What to monitor next in your Webflow Cloud app

Once one metric and one alert work end to end, the most useful additions are usually errors and logs, not more numbers. Error tracking answers what broke and where, which a metric never will.

If you already run Sentry for exceptions and want Datadog alongside it for logs, our Sentry and Datadog guide covers that combination directly. It avoids duplicating what each tool does best.

For the browser-side half, which needs no server code, the Webflow and Datadog integration covers Real User Monitoring and Synthetic tests against your published pages.

For the platform limits that shape all of this, including outbound request caps, timeouts and the Key-Value store, Webflow Cloud's limits are the page to read before designing anything that runs on every request.

Frequently asked questions

Can I install the Datadog Agent on Webflow Cloud?

No. The Agent is a daemon that runs on a host you control, and Webflow Cloud doesn't provide one. Instead, send data from your code to Datadog's HTTP intake API, or use Real User Monitoring and Synthetics, which run entirely outside your server.

Why can I not use the Cloudflare integration?

It is configured inside the Cloudflare account serving the traffic, and on Webflow Cloud that account is Webflow's rather than yours. The same applies to Logpush and to Cloudflare's own OpenTelemetry destinations, which are created in the Cloudflare dashboard.

Does APM tracing work?

Not with dd-trace, which depends on runtime internals that the Workers runtime doesn't expose. Datadog does accept OpenTelemetry traces over plain HTTP with no agent in between, so instrumenting with an OpenTelemetry SDK and exporting directly is the supported route.


Last Updated
September 4, 2026
Category

Related articles


verifone logomonday.com logospotify logoted logogreenhouse logoclear logocheckout.com logosoundcloud logoreddit logothe new york times logoideo logoupwork logodiscord logo
verifone logomonday.com logospotify logoted logogreenhouse logoclear logocheckout.com logosoundcloud logoreddit logothe new york times logoideo logoupwork logodiscord logo

Get started for free

Try Webflow for as long as you like with our free Starter plan. Purchase a paid Site plan to publish, host, and unlock additional features.

Get started — it’s free
Watch demo

Try Webflow for as long as you like with our free Starter plan. Purchase a paid Site plan to publish, host, and unlock additional features.