Guide

Running both adapters together

The edge connector on the zone route and the WooCommerce plugin at the origin, enforcing one queue from two places — why they compose, the setup order, and how to verify each layer.

The strongest configuration is both adapters at once: the Cloudflare edge connector on the zone route and the WooCommerce plugin at the origin. Each enforces the same signed policy with the same logic, and each covers what the other structurally cannot. This guide covers why they compose, the setup order, what the request path looks like, and how to verify that both are enforcing.

The sold topology: the edge sheds the crowd and admits; the plugin spends the pass at the money. Edge-only is fine for browse protection — it is not a complete commerce gate, because it has no notion of spending and one admission can fund more than one checkout. Prefer this setup for any store that takes payment.

Why they compose

A pass minted for one adapter is honoured by the other — same cookies, same verification keys, same binding — so the two are one queue, not two. What differs is position, and the differences are complementary.

Only the edge can: gate REST reads (/wp-json), which the plugin structurally cannot; defeat caches that answer without invoking PHP (server-level LiteSpeed, nginx microcaching, Varnish, CDN full-page caching); keep queued traffic off the origin entirely — the crowd never arrives; and rebind a legitimate shopper’s pass after an IP change or slide-refresh a near-expiry pass.

Only the plugin can: run the pass-spend lifecycle — reserve on order creation, finalise on confirmed payment, release on failure, the pending-order window; backstop order creation that touches neither cart nor checkout; catch commerce writes on transports the edge’s classifier does not describe; exempt WP-CLI, WP-Cron and staff from commerce gates; and keep gating through an outage on our side on durable state. That last one is the second-order argument for running both: an edge cold start during an outage fails open at Cloudflare, and the request then meets the plugin’s durable gate at the origin.

What the console shows for a two-adapter store

Nothing extra to configure. Every authorised key pull carries the adapter’s kind and the policy version it supports, and the console’s Install the adapter → Run check renders one row per kind — edge and woocommerce — with its reported version and a stale flag.

Two consequences worth knowing:

  • One outdated adapter downgrades both. Whole-shop gating and the allowlist are only emitted when every connected adapter supports the current policy version, because enabling the newer semantics on one adapter’s say-so would have the other interpreting the same policy under older meanings. Keep both current; the console warns when the effective version is below what it could be.
  • A removed adapter drops out after a day. Its report ages out and the effective version recovers — expiry is the safe direction.

Setup order

The order is not safety-critical — everything fails open — but this sequence gives you a verification point at each step:

  1. Plugin first, in shadow (plugin guide, steps 1–2): install, paste the setup code, Test connection now, read the shadow log. Run check now shows woocommerce.
  2. Then the edge (edge guide): same Store ID, same adapter key, same brain URL — one credential set serves both, and a key rotation invalidates both at once. Plan the allowlist (/wp-admin and friends) before the queue goes on; that is the edge guide’s step 3, and it matters more here because the edge answers first. After the first request traverses the Worker, Run check shows both kinds.
  3. Switch the plugin to enforce. Note the edge has no shadow mode: it enforces from the moment the queue is enabled in the console. Shadow-phase observations therefore come from the plugin’s log only.
  4. Enable the queue in the console when ready.

The request path with both enforcing

The edge decides first. Un-passed gated traffic is answered at Cloudflare (a redirect to the room, or a 503 with x-dropify-queue) and never reaches WordPress. Allowlisted and pass-holding requests are forwarded unmodified to the origin.

The origin then runs everything it would run alone. For an admitted request the plugin re-verifies the same pass locally — same keys, same binding, because behind Cloudflare the plugin’s default trusted-proxy list resolves the real client IP the way the edge did. The commerce hooks (add-to-cart, checkout, Store API, order creation) and the whole pass-spend lifecycle — reserve, pending window, finalise, spent markers — run at the origin exactly as in a plugin-only store. The browse gate still runs too; behind the edge it is normally redundant, which is precisely what makes it the outage backstop.

Division of labour on the queue’s edges:

  • Handoff: when a shopper is admitted from the room, the edge claims the handoff token, sets the cookies and redirects to the clean URL before WordPress ever sees the token.
  • Pass maintenance: IP rebind and sliding re-issue happen at the edge, which returns the fresh pass on the passthrough response; the plugin honours it on the next request. This upgrades a plugin-only weakness — alone, the plugin can neither rebind nor refresh.
  • Pass spending: origin only. The edge has no notion of spent, and it does not need one: spending does not clear the cookie, the buyer keeps browsing through the edge on a pass that still verifies, and every commerce request reaches the origin, where the plugin refuses a spent admission.

Order confirmation under the edge: one click

After a purchase, WooCommerce sends the buyer to the order-received page. Spending keeps their pass, so with the pass still alive they reach it — and keep browsing — without any special case. What still needs covering is a pass that expired between checkout and thank-you: a bank round trip can outlast the pass, or a drop reset can land in that window, and the edge, which answers first, would queue the buyer’s own confirmation page.

The fix is not an edge special case. It is a GET-only allowlist entry for the store’s real post-purchase paths, derived by the WooCommerce plugin from your permalink settings and applied through the normal allowlist:

  1. Run both adapters so Run check shows edge and woocommerce.
  2. Allowlist → Protect order confirmation → Protect N. It saves immediately.
  3. Done. The entries are GET-only; a POST to the order-pay page stays protected commerce.

Pretty permalinks are required — without them the plugin reports no safe path, because the alternative would ungate the shop.

Verifying both are enforcing

The edge fronts the origin, so you cannot probe the plugin’s browse gate independently from outside. Verify each layer by its own evidence:

  1. Edge: from a cookie-less client, a JSON-accepting request to a gated path must return 503 with x-dropify-queue, and an HTML-accepting one a 302 to the room. Those two shapes prove gating, not which layer did it — the plugin answers a data fetch identically, on purpose. Tell them apart by who built the response: an edge answer is served by Cloudflare and never reaches WordPress, so it carries no origin signature (server: cloudflare, no x-powered-by, no x-litespeed-cache-control) and leaves no entry in your origin access log. A plugin answer went through PHP and looks like it. The access log is the reliable one; header signatures depend on your origin’s own configuration.
  2. Both connected: console → Install the adapter → Run check → two rows, edge and woocommerce, both current. A stale WooCommerce row means no key pull in thirty minutes (often a quiet store); whole-shop gating is not dropped for that alone. Test connection now refreshes it.
  3. Plugin enforcing: the Settings → Dropify banner reads Connected and enforcing, mirrored in Site Health.
  4. The origin lifecycle actually ran: place a test order through the queue and check it in wp-admin — it should carry the _dropify_queue_pass and _dropify_queue_drop meta from the reserve step and _dropify_pass_finalized: yes after payment. That is direct evidence the origin enforcement path processed the purchase, independent of the edge.
  5. Watch both logs during the first drop: wrangler tail dropify-edge for queue and fail-open lines (the edge guide explains them), and the plugin’s WP_DEBUG log for ENFORCE queue: lines at the origin.

What the console can and cannot tell you

Adapters report no traffic counters. Every figure in the console — queued visitors, passes issued, average wait, peak concurrency — is something we witnessed ourselves (a real join, a real admission), so running both adapters cannot double-count anything. The flip side: there is no per-adapter breakdown. No “blocked at edge versus origin” number exists. Per-request visibility is wrangler tail at the edge and the WP_DEBUG log at the origin, nothing else.

Gaps that remain even with both

  • Order confirmation under the edge needs the one-click allowlist step above, and pretty permalinks.
  • Headless GraphQL storefronts are not supported. The console refuses a /graphql allowlist entry; under whole-shop gating the endpoint needs a pass like any other path, and on a store with the plugin, cart and checkout mutations are refused at the origin regardless of transport — which is what makes the combined deployment the right one for a store that has WPGraphQL installed at all. Quantity edits on a line already in the cart are limited by the per-pass unit cap on every transport.
  • The edge still gates /wp-admin and /wp-login.php under whole-shop gating — the allowlist in the edge guide applies unchanged.
  • After a purchase, only buying is locked; the buyer keeps browsing on their pass until it expires. A second purchase needs a new place in the queue.
  • LiteSpeed Cache: the cookie exclusions and the wp-content/litespeed/* → Worker: None route from the plugin guide apply here too.

← All guides