Lookout
000 015 030 045 060 075 090 105 120 135 150 165 180 195 210 225 240 255 270 285 300 315 330 345 360
Documentation Edge ingest (Cloudflare)

Edge ingest on Cloudflare

Deploy an optional edge ingest tier when you operate Lookout at high volume. Customers keep the same project API key and POST /api/ingest contract; you give them an edge hostname for their DSN instead of the main app URL.

This guide is for Lookout operators (your deployment .env and Cloudflare account). Customer SDKs do not need extra env vars.

How it works

Customer app  →  Cloudflare Worker (/api/ingest, project API key)
                      ↓ KV validate, 202 immediately
                 Cloudflare Queue
                      ↓ Bearer LOOKOUT_INGEST_EDGE_TOKEN
                 Lookout backend  POST /api/ingest/edge  →  queue  →  MySQL
Hop Authentication
Customer → Worker Project API key (X-Api-Key / Bearer) validated against Workers KV
Worker → Lookout Shared secret LOOKOUT_INGEST_EDGE_TOKEN as Authorization: Bearer …

The edge token is not a project API key. Generate it once and store the same value on Lookout and in the Worker secret.

Prerequisites

  • A running Lookout deployment with Redis, queue workers (Horizon or queue:work), and the same database the UI uses.
  • A Cloudflare account with Workers, Workers KV, and Queues enabled.
  • Wrangler CLI (npm install -g wrangler or use the package-local devDependency).
  • Worker source in this repo: packages/lookout-ingest-edge/.

Step 1 — Generate LOOKOUT_INGEST_EDGE_TOKEN

On your machine:

openssl rand -hex 32

Copy the output. You will set this identical string in two places:

  1. Lookout server .envLOOKOUT_INGEST_EDGE_TOKEN=…
  2. Cloudflare Worker secret → wrangler secret put LOOKOUT_INGEST_EDGE_TOKEN

Treat it like an internal service password. Rotate by updating both sides and redeploying the worker.

Step 2 — Configure Lookout (backend)

Add to the Lookout app .env (UI + ingest backend, or ingest-only hosts that receive forwarded events):

LOOKOUT_INGEST_EDGE_ENABLED=true
LOOKOUT_INGEST_EDGE_TOKEN=paste-the-openssl-output-here
LOOKOUT_INGEST_EDGE_BACKEND_URL=https://your-lookout-app.example.com

CLOUDFLARE_ACCOUNT_ID=your-account-id
CLOUDFLARE_KV_NAMESPACE_ID=your-kv-namespace-id
CLOUDFLARE_API_TOKEN=token-with-kv-edit-and-workers-read
Variable Purpose
LOOKOUT_INGEST_EDGE_ENABLED Enables KV sync schedule and high-volume ingest optimizations
LOOKOUT_INGEST_EDGE_TOKEN Must match the Worker secret; secures POST /api/ingest/edge
LOOKOUT_INGEST_EDGE_BACKEND_URL Public base URL of Lookout (no trailing slash); Worker consumer posts here
CLOUDFLARE_* Used by php artisan lookout:sync-ingest-edge-keys to push project API keys into KV

Create a Cloudflare API token with Workers KV Storage → Edit on the ingest namespace and account read access. Restrict to the minimum scopes you need.

Reload config (php artisan config:clear or redeploy). The internal forward route is:

POST https://uselookout-2ku5bv.on-dply.com/api/ingest/edge

It returns 503 until LOOKOUT_INGEST_EDGE_TOKEN is set.

Step 3 — Create KV namespace and Queue (Cloudflare)

From packages/lookout-ingest-edge/:

cd packages/lookout-ingest-edge
npm install
npx wrangler login
npx wrangler kv namespace create INGEST_KEYS
npx wrangler queues create lookout-ingest

Note the namespace id from the KV create output and paste it into:

  • Lookout .envCLOUDFLARE_KV_NAMESPACE_ID
  • wrangler.toml[[kv_namespaces]]id = "…"

Ensure wrangler.toml queue name matches (lookout-ingest).

Step 4 — Configure wrangler.toml

Edit packages/lookout-ingest-edge/wrangler.toml:

[vars]
LOOKOUT_BACKEND_URL = "https://your-lookout-app.example.com"

Set max_concurrency under [[queues.consumers]] to match how much load your Lookout backend can absorb (start with 25, tune with Horizon).

Step 5 — Set Worker secrets and deploy

Still in packages/lookout-ingest-edge/:

npx wrangler secret put LOOKOUT_INGEST_EDGE_TOKEN
# paste the same value as in Lookout .env

npm run deploy

Wrangler prints the *.workers.dev URL and any custom domains from wrangler.toml.

If your Lookout marketing/app zone is on the same Cloudflare account as the Worker, add a custom domain in packages/lookout-ingest-edge/wrangler.toml:

workers_dev = true

[[routes]]
pattern = "ingest.uselookout.app"
custom_domain = true

Run npm run deploy again. Cloudflare creates the DNS record and TLS certificate automatically — no manual CNAME required.

This deployment: https://ingest.uselookout.app (plus the *.workers.dev URL for testing).

To use a different hostname, change pattern and redeploy. The zone (e.g. uselookout.app) must be active on the account you wrangler login with.

Dashboard alternative: Workers & Pages → lookout-ingest-edgeSettings → Domains & Routes → Add → Custom Domain.

The worker only handles POST /api/ingest (same path as today).

Step 6 — Sync project API keys to KV

On the Lookout server:

php artisan lookout:sync-ingest-edge-keys

When LOOKOUT_INGEST_EDGE_ENABLED=true, this also runs every five minutes via the scheduler. Keys refresh when a project API key is regenerated.

Verify a key exists (replace values):

npx wrangler kv key get --binding=INGEST_KEYS "PROJECT_API_KEY_HERE"

You should see JSON with project_id, billing_ok, etc.

Step 7 — Point customer DSNs at the edge

Customers change only the host in their DSN / ingest URL:

# Before (main app)
LOOKOUT_DSN=https://PROJECT_API_KEY@lookout.example.com

# After (edge — custom domain)
LOOKOUT_DSN=https://PROJECT_API_KEY@ingest.uselookout.app

# Or workers.dev during testing
# LOOKOUT_DSN=https://PROJECT_API_KEY@lookout-ingest-edge.flat-thunder-531a.workers.dev

Same API key, same payload, same POST /api/ingest. No new SDK env vars.

Step 8 — Verify end-to-end

  1. Edge accept — from any machine:

    curl -sS -o /dev/null -w "%{http_code}\n" \
      -X POST "https://ingest.uselookout.app/api/ingest" \
      -H "X-Api-Key: YOUR_PROJECT_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"message":"edge smoke test","exception_class":"RuntimeException"}'
    

    Expect 202.

  2. Lookout UI — open the project; the event should appear after the queue consumer forwards and StoreIngestedEvent runs.

  3. Bad edge token — if the Worker secret and Lookout .env token differ, the consumer logs forward failures and events will not persist.

Mode Env Doc
Dedicated ingest app servers LOOKOUT_INGEST_ONLY=true Ingest satellite README
Force deferred DB side-effects without edge LOOKOUT_INGEST_MINIMAL_IMPACT=true Ingest API — high volume

Edge ingest and ingest-only mode automatically defer non-critical writes (api_key_last_used_at, release markers) to a Redis flush every 30 seconds.

Troubleshooting

Symptom Check
Edge returns 401 API key missing from KV — run lookout:sync-ingest-edge-keys
Edge returns 402 Organization billing delinquent in synced KV metadata
Edge returns 403 Client IP blocked by org ingest allowlist
Lookout 503 on /api/ingest/edge LOOKOUT_INGEST_EDGE_TOKEN unset on Lookout
Events accepted at edge but not in UI Queue consumer errors — Cloudflare dashboard → Queues; Worker logs; Horizon processing StoreIngestedEvent
Stale billing / IP rules Wait for sync schedule or run sync manually after org settings change

Package reference

Monorepo path: packages/lookout-ingest-edge/ (Worker source, wrangler.toml, npm run deploy).