INTEGRITY Documentation

Transformers

Beta

Transformers let you run a SQL query against each batch of records before Logpush delivers them to your destination. Use them to filter records you do not want to store, reshape fields to match a downstream schema, redact sensitive values, compute new fields, or add static metadata.

You write the logic as a single SQL query, attach it to a Logpush job, and Cloudflare runs it on every batch. The FROM clause names the Logpush dataset (for example, http_requests or audit_logs_v2) and field names come from that dataset's schema.

Key features

Before you begin, you need:

Access Transformers

You can create, preview, attach, and manage transformers through the Cloudflare dashboard or the API.

Transformer Studio (UI)

Transformer Studio is the workspace that includes a SQL editor where you write, preview, and manage Transformers. Open it from the Logpush page in the Cloudflare dashboard.

Go to Logpush ↗

From Studio you can:

API

Every transformer action is available through the Cloudflare API. To authenticate, use an API token with the Logs Write permission.

Operation Method Endpoint
List transformers GET accounts/:account_id/logpush/transformers
Create a transformer POST accounts/:account_id/logpush/transformers
Preview a transformer POST accounts/:account_id/logpush/transformers/preview
Get a transformer GET accounts/:account_id/logpush/transformers/:id
Download SQL GET accounts/:account_id/logpush/transformers/:id/content
List versions GET accounts/:account_id/logpush/transformers/:id/versions
Update a transformer PUT accounts/:account_id/logpush/transformers/:id
Delete a transformer DELETE accounts/:account_id/logpush/transformers/:id

To attach or detach a transformer from a job, set transformer_id on the Logpush job. Refer to Logpush job setup for job endpoints.

The SQL transformer contract

A transformer is a single SQL query. The Logpush dataset is the source table; the query output becomes the delivered record.

SELECT ClientIP, RayID, EdgeResponseStatus
FROM http_requests
WHERE EdgeResponseStatus >= 400

The FROM table name must match the dataset of the Logpush job the transformer is attached to. If it does not, attachment fails.

Records that do not match the WHERE clause are dropped from the output.

Supported SQL

Transformers use the same SQL dialect as Cloudflare Pipelines. The following operations are supported:

Not supported

Validation

Every SQL query is validated against the target dataset's schema before it is saved. Unknown fields, wrong types, invalid syntax, unknown datasets, and unsupported operations are rejected at upload time.

In the dashboard, validation errors appear inline in the editor with line and column numbers. Through the API, they are returned in the errors array of the response.

Limits

Limit Value
SQL query size 10 KB
Transformer name length 255 bytes
Transformer description length 4,096 bytes
Filesystem access from a query None
Network access from a query None
Batch chunk size 1,000 rows

Examples

The examples below apply every capability from Key features in a single query. Each keeps a subset of records, reshapes the survivors, and drops fields the downstream pipeline does not need.

Filter and reshape audit log records

This transformer keeps only update actions from the audit trail and reshapes the surviving records for downstream delivery. Specifically, it:

Input record from the audit_logs_v2 dataset:

{
  "ActionType": "update",
  "ActorEmail": "[email protected]",
  "ActorID": "a1b2c3d4",
  "ActorIPAddress": "203.0.113.42",
  "ActorType": "user",
  "ActionTimestamp": "2026-05-21T15:00:00Z",
  "AccountID": "90796717",
  "ResourceID": "r1s2t3u4",
  "ResourceType": "zone",
  "ActorContext": "dashboard"
}

Transformer:

SELECT
  extract(epoch FROM to_timestamp(ActionTimestamp)) AS unix_ts,
  UPPER(ActionType) AS action_type,
  'Cloudflare' AS provider,
  named_struct(
    'type', ActorType,
    'email', ActorEmail,
    'ip', ActorIPAddress
  ) AS actor,
  ResourceType = 'zone' AS is_zone,
  [ResourceType, ResourceID] AS resource_meta
FROM audit_logs_v2
WHERE ActionType = 'update'

Delivered record:

{
  "action_type": "UPDATE",
  "actor": {
    "email": "[email protected]",
    "ip": "203.0.113.42",
    "type": "user"
  },
  "is_zone": true,
  "provider": "Cloudflare",
  "resource_meta": ["zone", "r1s2t3u4"],
  "unix_ts": 1779375600
}

Filter and reshape HTTP request records

This transformer keeps all HTTP traffic except health checks, metrics scrapers, and internal-facing hostnames. This is a common pattern for teams that want the full log stream, minus predictable noise. Specifically, it:

Input record from the http_requests dataset:

{
  "ClientIP": "203.0.113.42",
  "ClientRequestHost": "example.com",
  "ClientRequestMethod": "POST",
  "ClientRequestPath": "/api/checkout",
  "ClientRequestUserAgent": "curl/7.85.0",
  "EdgeResponseStatus": 502,
  "EdgeStartTimestamp": "2026-05-21T15:00:00Z",
  "RayID": "8e2a1c60ef9e1c9a",
  "OriginResponseTime": 3200000000,
  "WAFAction": "unknown"
}

This example assumes EdgeStartTimestamp is delivered as an RFC3339 string. If your job delivers timestamps as Unix nanoseconds, drop the to_timestamp() wrapper and divide by 1e9 instead.

Transformer:

SELECT
  extract(epoch FROM to_timestamp(EdgeStartTimestamp)) AS unix_ts,
  UPPER(ClientRequestMethod) AS method,
  'Cloudflare' AS provider,
  named_struct(
    'host', ClientRequestHost,
    'path', ClientRequestPath,
    'method', ClientRequestMethod
  ) AS request,
  EdgeResponseStatus >= 500 AS is_server_error,
  [ClientRequestHost, ClientRequestPath] AS request_meta
FROM http_requests
WHERE ClientRequestHost NOT IN ('internal.example.com', 'health.example.com')
  AND ClientRequestPath NOT LIKE '/healthz%'
  AND ClientRequestPath NOT LIKE '/metrics%'

Delivered record:

{
  "is_server_error": true,
  "method": "POST",
  "provider": "Cloudflare",
  "request": {
    "host": "example.com",
    "method": "POST",
    "path": "/api/checkout"
  },
  "request_meta": ["example.com", "/api/checkout"],
  "unix_ts": 1779375600
}

Errors and troubleshooting

API errors

HTTP Message Cause
403 transformer feature is not available for this account Your account does not have access to Transformers. Contact your Cloudflare Account Executive.
400 missing required field: name Add a name field to the request body.
400 missing required field: code Add a non-empty code field with your SQL query.
400 Schema validation error (unknown column, invalid syntax) The SQL references a field that does not exist, uses unsupported syntax, or has a type mismatch. Fix the query and retry.
413 (request entity too large) The SQL query exceeds 10 KB. Shorten the query.
400 transformer N not found for this account The transformer ID does not exist, or belongs to a different account.
400 transformer N dataset "X" does not match job dataset "Y" The transformer's FROM table does not match the job's dataset.

Runtime failures

If a transformer fails while processing a batch, the batch fails: nothing is delivered for it, an error is recorded on the Logpush job, and Logpush retries the batch on its normal schedule. There is no automatic raw-log fallback.

If failures continue, records in the affected batches are eventually dropped and cannot be recovered.

The last error appears on the job's last_error field. Common causes:

To debug, open the transformer in Transformer Studio and use the Run button to preview it against a sample record. Validation and execution logic are the same, so problems visible in production usually reproduce in preview.