GetDatabase icon
OutputValues icon
If icon
SlackIncomingWebhook icon
Log icon
Schedule icon

Cloudflare D1 Database Size Quota Gate

Fetch a Cloudflare D1 database's size, alert Slack when it reaches a quota you declare, and log the result for platform teams.

Categories
CloudInfrastructure

A Cloudflare D1 database that quietly grows toward its plan's size limit does not page anyone until a write starts failing in production. Cloudflare's own dashboard shows the current size if someone opens it; it has no built-in alert for "this database is approaching its quota." This blueprint reads the real file size directly and compares it against a threshold you set.

This blueprint was created by Mohit Jeswani.

How it works

  1. get_database (io.kestra.plugin.cloudflare.d1.GetDatabase) fetches database_id's current fileSize, table count, and engine version. Read-only; nothing in Cloudflare is changed. allowFailure: true covers an API or auth error without failing the flow outright.
  2. evaluate (io.kestra.plugin.core.output.OutputValues) compares fileSize against max_size_bytes. A failed fetch is also treated as CRITICAL, the same severity as an actual quota breach.
  3. route (io.kestra.plugin.core.flow.If):
    • compliant: logs the current size, below quota.
    • alert: posts the size and quota to Slack.
  4. summary logs the size and severity, closing the governance cycle.
  5. errors alerts Slack if the flow itself fails, for example an expired API token.

What you get

  • A direct read of the database's real size, not an estimate, compared against a quota you control rather than discovering the limit when a write first fails.
  • A failed fetch and a genuine quota breach both surface, with the Slack text making clear which one happened.
  • A full execution history of every check, so slow growth toward the limit is visible over time, not just at the moment it crosses.

Who it's for

  • Platform and data teams running Cloudflare D1 databases who want size growth watched between deploys, not discovered as a production write failure.
  • Teams evaluating the Cloudflare plugin who want a worked example of d1.GetDatabase used as a standing resource quota check rather than a one-off lookup.

Why orchestrate this with Kestra

Cloudflare reports the database's size; it does not decide what quota is safe for your plan, compare the real size against it, or notify anyone as it approaches the limit. Kestra keeps max_size_bytes as a flow input instead of institutional memory, turns a size check into a Slack page naming the exact byte count, and keeps a full execution history of every run.

Prerequisites

  • A Cloudflare account with at least one D1 database already created.
  • A Cloudflare API token with D1 read permission for the account.
  • A Slack incoming webhook URL.

This flow calls the Cloudflare API directly over HTTPS; there is no official local Cloudflare D1 emulator this task can be pointed at, so get_database cannot be exercised against a local Docker container. Validate against a real, non-production database first.

Secrets

  • CLOUDFLARE_API_TOKEN: the Cloudflare API token used by get_database. In Kestra OSS, provide it as the base64-encoded environment variable SECRET_CLOUDFLARE_API_TOKEN.
  • SLACK_WEBHOOK_URL: used by alert and the errors block. In Kestra OSS, provide it as the base64-encoded environment variable SECRET_SLACK_WEBHOOK_URL.

Inputs

Input Default Purpose
account_id <your-cloudflare-account-id> Cloudflare account owning the database
database_id <your-d1-database-id> D1 database to check
max_size_bytes 524288000 (500 MB) fileSize at or above this triggers the alert

Outputs

  • {{ outputs.get_database.fileSize }}: current database size in bytes.
  • {{ outputs.get_database.numTables }} / .version: additional metadata returned alongside size.
  • {{ outputs.evaluate.values.severity }}: OK, QUOTA_EXCEEDED, or CRITICAL.

Pitfalls

  • max_size_bytes is whatever you set it to; this blueprint does not look up your Cloudflare plan's actual D1 limit. Set it below your real plan ceiling with a safety margin, not equal to it, since write volume between scheduled checks can still push the database over the real limit before the next run catches it.
  • fileSize reflects the database file on disk, which can include unreclaimed space from deletes depending on D1's internal storage behavior; a size near quota does not always mean an equivalent amount of live data.
  • A CRITICAL result (fetch failed) and a QUOTA_EXCEEDED result (fetch succeeded, size at or above threshold) are both routed to the same alert branch; read the Slack message's size_bytes value to tell them apart, it reads -1 only on a failed fetch.

Quick start

  1. Add the CLOUDFLARE_API_TOKEN and SLACK_WEBHOOK_URL secrets.
  2. Set account_id and database_id to a real D1 database.
  3. Run the flow manually and confirm compliant logs the real size.
  4. Lower max_size_bytes below that real size to confirm alert fires with QUOTA_EXCEEDED.
  5. Restore max_size_bytes to a real threshold below your plan's limit, then enable the hourly trigger.

How to extend

  • Loop over several database_id values with io.kestra.plugin.core.flow.Loop to watch every D1 database in an account in one scheduled run.
  • Chain io.kestra.plugin.cloudflare.d1.Export after a QUOTA_EXCEEDED result to trigger a backup before the database grows further.
  • Track size_bytes over successive runs in a KV entry to graph growth rate, not just the current size, so you can project when the real quota will be reached.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.