Skip to content

Infrastructure Resources

This page is the ops-level inventory of every Cloudflare and PlanetScale resource the platform depends on. It complements the Physical Architecture (which maps logical components to infrastructure) and the Architecture Decision Records (which explain why each choice was made). Use this page when provisioning a new environment, auditing costs, or onboarding someone to the infrastructure.

graph TB
  subgraph "Cloudflare Edge"
    Pages["Pages<br/>(React SPA + Docs)"]
    Access["CF Access<br/>(Google SSO)"]

    subgraph "Workers (Compute)"
      DashAPI["dashboard-api<br/>(Hono, staff API)"]
      Ingest["ingest<br/>(Workflows, queue consumer)"]
      PlatformAPI["platform-api<br/>(public API)"]
    end

    subgraph "Durable Execution"
      Workflows["CF Workflows<br/>(6 workflows)"]
      DO["Durable Objects<br/>(watermark state)"]
    end

    Queue["Queue: ingest-queue"]
    KV["KV Namespace<br/>(config cache)"]

    subgraph "Analytics"
      Pipelines["Pipelines<br/>(3 telemetry streams)"]
      WAE["Workers Analytics Engine<br/>(real-time counters)"]
    end

    subgraph "Storage"
      R2Assets["R2: Design Assets"]
      R2Archive["R2: JSONL Archive"]
      R2Catalog["R2 Data Catalog<br/>(Iceberg tables)"]
    end
  end

  subgraph "External"
    PS["PlanetScale<br/>(PostgreSQL)"]
    Shopify["Shopify Admin API"]
    Dropbox["Dropbox"]
    HD["Hyperdrive<br/>(connection pool)"]
  end

  Access -->|JWT gate| Pages
  Access -->|JWT gate| DashAPI
  Pages -->|API proxy| DashAPI
  DashAPI -->|Service Binding| Ingest
  DashAPI -->|send| Queue
  Queue -->|consume| Ingest
  Ingest --> Workflows
  Workflows --> DO
  Ingest -->|stream push| Pipelines
  PlatformAPI -->|stream push| Pipelines
  Pipelines --> R2Catalog
  Ingest --> R2Assets
  Ingest --> R2Archive
  DashAPI --> HD
  Ingest --> HD
  PlatformAPI --> HD
  HD --> PS
  Ingest --> Shopify
  Ingest --> Dropbox
  PlatformAPI -->|write| WAE
Resource TypeNamePurposeUsed By (scenarios)
Workerdashboard-apiStaff-facing HTTP APIAll staff scenarios
Workerplatform-apiPublic API (publishers, telemetry)Publisher telemetry, public endpoints
WorkeringestQueue consumer, Workflow executor, archivalBulk Sync, Asset Ingest, CSV Export, Combo Suggestions
CF WorkflowShopify Bulk SyncMulti-step order/product syncBulk Sync
CF WorkflowMeasurement RefreshDuckDB aggregation over IcebergPerformance Metrics, Tag Analytics
CF WorkflowAsset IngestDropbox to R2 to Shopify metafieldAsset Ingest
CF WorkflowCSV ExportQuery, format, upload to R2CSV Export
CF WorkflowSuggestion GenerationGenerate combo suggestions from metricsCombo Suggestions
CF WorkflowCombo ImportParse CSV, upsert combo reportsCombo CRUD
Queueingest-queueJob dispatch (typed discriminator)All background jobs
R2 BucketDesign assetsProduct design imagesAsset Ingest
R2 BucketJSONL archiveBulk sync audit trail, CSV exportsBulk Sync, CSV Export
R2 Data CatalogIceberg tablesAnalytics retention (3 telemetry + 3 measurement)Performance Metrics, Pipeline
PipelineCOMMERCE_TELEMETRYOrder lifecycle eventsBulk Sync
PipelinePUBLICATION_TELEMETRYClicks, impressions, viewsPublisher telemetry
PipelineSYNC_TELEMETRYWorkflow audit trailAll Workflows
Durable ObjectWatermark singletonCursor state for incremental syncBulk Sync
KV NamespaceConfig cacheFeature flags, classification thresholdsOptional — all scenarios
Analytics EngineReal-time countersClicks, impressions, page viewsPublisher telemetry
PagesDashboard SPAReact frontendAll staff scenarios
PagesDocs siteThis documentationN/A
CF AccessApplication policyGoogle SSO gateAll staff scenarios
HyperdriveConnection poolPlanetScale connection optimizationAll Workers
PlanetScalePostgreSQL databaseDomain/transactional store (153 tables)All scenarios

The platform runs three Workers, each with a distinct trust boundary and binding set.

The primary HTTP surface for the React dashboard. Protected by Cloudflare Access (Google SSO). Built with Hono.

Bindings:

BindingTypePurpose
HYPERDRIVEHyperdrivePlanetScale connection pooling
R2_BUCKETR2 BucketAsset reads, CSV export downloads
INGEST_QUEUEQueue (producer)Dispatch background jobs
INGESTService BindingDirect calls to the ingest Worker (health, status)
KVKV NamespaceOptional config/feature flag cache
SHOPIFY_ACCESS_TOKENSecretShopify API auth
CF_ACCESS_AUDVariableAccess application audience tag for JWT validation

Routes overview:

Route groupEndpointsModule
/api/performance-metricsCRUD, sync trigger, classification settingsPerformance
/api/combo-logsCRUD, import, exportCombos
/api/combo-templatesCRUDCombos
/api/combo-suggestionsGenerate, list, acceptCombos
/api/products/tagsTag sync, classification, groupsTags
/api/tag-analyticsPerformance, distribution, refreshTags
/api/tag-groupsCRUDTags
/api/assetsIngest trigger, statusAssets
/api/csvGenerate, list, downloadCSV Exports
/api/ordersLookupOrders
/api/designersList, assign, unassignDesigner Assignment
/api/fulfillment-daily-summaryRead-onlyFulfillment
/api/healthService + Workflow statusHealth

See the full endpoint inventory in the Scenarios Overview.

The public-facing API for publishers, affiliate tracking, and engagement telemetry. Authenticated via API keys or OAuth — not behind CF Access.

Bindings:

BindingTypePurpose
HYPERDRIVEHyperdrivePlanetScale connection pooling
PUBLICATION_TELEMETRYPipelineStream engagement events
ANALYTICS_ENGINEAnalytics EngineReal-time click/impression counters
KVKV NamespaceOptional config cache

Responsibilities:

  • Serve public product/publication data
  • Capture engagement telemetry (clicks, impressions, views)
  • Handle publisher authentication and commission lookups

ingest — queue consumer and Workflow executor

Section titled “ingest — queue consumer and Workflow executor”

The background processing Worker. Consumes from the ingest-queue, executes all 6 CF Workflows, handles Shopify webhooks, and pushes enriched events to Pipeline streams.

Bindings:

BindingTypePurpose
HYPERDRIVEHyperdrivePlanetScale connection pooling
R2_BUCKETR2 BucketAsset uploads, JSONL archival, CSV writes
INGEST_QUEUEQueue (consumer)Receive dispatched jobs
COMMERCE_TELEMETRYPipelineStream commerce events
PUBLICATION_TELEMETRYPipelineStream publication events
SYNC_TELEMETRYPipelineStream Workflow audit events
WATERMARK_DODurable ObjectRead/write sync cursor state
SHOPIFY_ACCESS_TOKENSecretShopify API auth

Queue consumer config:

[[queues.consumers]]
queue = "ingest-queue"
max_batch_size = 10
max_batch_timeout = 5

Cron Triggers (defined in wrangler.toml):

CronScheduleWorkflow started
0 6 * * *Daily 06:00 UTCShopify Bulk Sync
0 * * * *HourlyMeasurement Refresh
0 3 * * 0Weekly, Sunday 03:00 UTCAsset Health Check

All six Workflows run inside the ingest Worker. Each is a durable multi-step execution with automatic retries and replay. Persistent failures emit error events to SYNC_TELEMETRY for long-term audit retention.

Synchronizes orders, products, and related data from Shopify via the GraphQL Bulk Operations API. See Daily Shopify Bulk Sync.

PropertyValue
TriggerCron (0 6 * * *) or manual via POST /api/performance-metrics/sync
StepsInitiate -> Request bulk query -> Poll until complete -> Download JSONL -> Parse + upsert to PG -> Enrich + stream to COMMERCE_TELEMETRY -> Advance watermark in DO
BindingsHYPERDRIVE, R2_BUCKET (archive), COMMERCE_TELEMETRY, SYNC_TELEMETRY, WATERMARK_DO, SHOPIFY_ACCESS_TOKEN

Replaces the old PG-based materialized view refresh. Runs DuckDB over R2 Iceberg tables to compute sliding-window aggregates and nominal classifications. See Pipeline.

PropertyValue
TriggerCron (0 * * * * — hourly)
StepsQuery commerce.telemetry Iceberg table -> Compute 7/14/30-day windows -> Classify against objective spec thresholds -> Write measurement.sales + measurement.performance Iceberg tables
BindingsR2_BUCKET (Iceberg read/write), SYNC_TELEMETRY

Downloads design assets from Dropbox, uploads to R2, links to products in PG, and writes the Shopify metafield. See Asset Ingest.

PropertyValue
TriggerAPI (POST /api/assets/ingest) -> Queue -> Workflow
StepsDownload from Dropbox -> Content hash + dedup -> Upload to R2 -> Link product in PG -> Write Shopify metafield
BindingsHYPERDRIVE, R2_BUCKET (asset upload), SYNC_TELEMETRY, SHOPIFY_ACCESS_TOKEN

Generates downloadable CSV files from domain queries and stores them on R2. See CSV Export.

PropertyValue
TriggerAPI (POST /api/csv/generate) -> Queue -> Workflow
StepsQuery PG domain tables -> Format CSV -> Upload to R2 -> Record artifact in PG
BindingsHYPERDRIVE, R2_BUCKET (CSV upload), SYNC_TELEMETRY

Generates combo suggestions from measurement data and performance metrics. See Combo Suggestions.

PropertyValue
TriggerAPI (POST /api/combo-suggestions/generate) -> Queue -> Workflow
StepsQuery measurement.performance Iceberg table -> Generate suggestion artifacts -> Write macrodata_artifact records to PG
BindingsHYPERDRIVE, R2_BUCKET (Iceberg read), SYNC_TELEMETRY

Parses uploaded CSV files and upserts combo report artifacts. See Combo CRUD.

PropertyValue
TriggerAPI (POST /api/combo-logs/import) -> Queue -> Workflow
StepsParse CSV payload -> Validate rows against schema -> Upsert macrodata_artifact (kind: combo_report) records in PG
BindingsHYPERDRIVE, SYNC_TELEMETRY

A single Cloudflare Queue with a job_type discriminated union (ADR-005). The dashboard-api Worker produces messages; the ingest Worker consumes them.

Configuration:

SettingValue
Queue nameingest-queue
Max batch size10
Max batch timeout5 seconds
Retry limit3 (default)
Dead Letter QueueRecommended for poison message handling

Job types (Zod discriminated union):

job_typeDispatched byWorkflow started
SHOPIFY_BULK_SYNC_STARTCron / APIShopify Bulk Sync
ASSET_INGESTPOST /api/assets/ingestAsset Ingest
DOCUMENT_ARTIFACT_GENERATEPOST /api/csv/generateCSV Export
MEASUREMENT_DATASET_REFRESHCronMeasurement Refresh
SUGGESTION_GENERATEPOST /api/combo-suggestions/generateSuggestion Generation
COMBO_IMPORTPOST /api/combo-logs/importCombo Import

All messages flow through the same queue and share retry/DLQ configuration. The trade-off is noisy-neighbor risk if one job type floods the queue, mitigated by batch size configuration.

Three logical R2 buckets (may be consolidated into fewer physical buckets with prefix-based separation).

Stores product design images. Served via a public R2 custom domain.

PropertyValue
Path patternassets/{hash_prefix}/{filename}
Public URLhttps://assets.bluntcases.com/{key}
AccessWorker binding (env.R2_BUCKET) + public custom domain
Used byAsset Ingest
Content typesPNG, JPG, SVG, PDF, WebP

Stores raw Shopify bulk operation results for audit and replay, plus generated CSV exports.

PropertyValue
Path pattern (archives)archives/ingest/{run_id}.jsonl
Path pattern (exports)exports/csv/{export_id}.csv
AccessWorker binding only (not public)
Used byBulk Sync, CSV Export

Managed Apache Iceberg tables on R2, written by Cloudflare Pipelines and the Measurement Refresh Workflow. Queryable via the Iceberg REST catalog interface by DuckDB, Spark, Trino, or Cloudflare R2 SQL.

Iceberg tableSourcePartitioningDescription
commerce.telemetryCOMMERCE_TELEMETRY PipelineDailyOrder lifecycle events
publication.telemetryPUBLICATION_TELEMETRY PipelineHourlyEngagement events (clicks, impressions, views)
sync.telemetrySYNC_TELEMETRY PipelineDailyWorkflow execution audit trail
measurement.salesMeasurement Refresh WorkflowDailyDaily sales aggregates by product x day
measurement.performanceMeasurement Refresh WorkflowDailyAggregated metrics with sliding windows + nominal classification
configuration.objective_specReplicated from PGUnpartitionedClassification thresholds (co-located with analytics for query performance)

See Pipeline for details on each table.

Three dedicated streaming ingestion pipelines (ADR-008). Workers push enriched events via env.STREAM.send(); Pipelines applies stateless SQL transforms and lands Iceberg/Parquet tables on R2 Data Catalog.

PropertyValue
Eventsorder_created, order_completed, payment_captured, payment_refunded, fulfillment_shipped, return_requested
VolumeMedium (order throughput)
Iceberg tablecommerce.telemetry
PartitioningDaily
Produceringest Worker (after PG domain write + enrichment)
PropertyValue
Eventsclick, impression, view, engagement, conversion — enriched with publisher/item/program context
VolumeHigh (every visitor interaction)
Iceberg tablepublication.telemetry
PartitioningHourly
Producerplatform-api Worker (may skip PG for raw engagement events)
PropertyValue
EventsWorkflow completions with record counts, watermark positions, durations
VolumeLow (operational audit trail)
Iceberg tablesync.telemetry
PartitioningDaily
Produceringest Worker (at Workflow step boundaries)

Beta constraints (as of Pipelines open beta): 20 streams per account, 5 MB/s per stream, 1 MB max payload per request. The platform uses 3 of the 20 available streams.

A Durable Object singleton manages incremental sync state for the Shopify Bulk Sync Workflow (ADR-009). This keeps pipeline orchestration state out of PlanetScale entirely.

Stored state:

{
"key": "orders_last_watermark",
"value_json": { "ts": "2026-02-19T06:00:00Z" }
}

Behavior:

  • Read at Workflow start to determine the updated_at filter for Shopify bulk queries
  • Advanced only after successful Workflow step completion
  • Hard floor: 128 days back — watermarks older than this reset to NOW() - 128 days
  • Historical loads beyond 128 days use a separate full backfill Workflow

Binding:

[durable_objects]
bindings = [
{ name = "WATERMARK_DO", class_name = "WatermarkDO" }
]

A KV namespace for caching configuration data and feature flags. This is optional — the system works without it, falling back to direct PG reads.

PropertyValue
BindingKV
Use casesClassification thresholds, feature flags, cached lookup data
TTLApplication-defined per key
Consumersdashboard-api, platform-api
[[kv_namespaces]]
binding = "KV"
id = "your-kv-namespace-id"

Real-time counters for high-frequency events that need sub-second reads but not long-term Iceberg retention. Writes happen in parallel with Pipeline stream pushes — not sequentially.

PropertyValue
BindingANALYTICS_ENGINE
Data points20 blobs + 20 doubles per data point
Retention3 months (automatic)
SamplingAutomatic at high volume
CountersClicks, impressions, page views
QuerySQL API or Grafana integration
Consumersplatform-api Worker

The Analytics Engine handles the real-time read path (dashboards, live counters), while Pipelines handles the long-term retention path (Iceberg tables for historical analysis). See Pipeline: Real-time counters.

The React frontend, built with Vite and deployed to Cloudflare Pages.

PropertyValue
Buildcd client && npm run build (Vite)
RoutingSPA fallback — all paths resolve to index.html
API proxyPages Functions or custom domain routing to dashboard-api Worker
AuthCF Access gate sits in front of Pages (user authenticates before the app loads)

This Astro Starlight documentation site, also deployed to Cloudflare Pages.

Cloudflare Access is the single authentication layer (ADR-001). There is no auth UI in the application itself. See Authentication for the full details.

PropertyValue
Identity providerGoogle Workspace SSO
Protected resourcesDashboard SPA (Pages), dashboard-api Worker
Token deliveryCf-Access-Jwt-Assertion header
RBACNot in v1 — all authenticated staff have equal access
PolicyScopeRule
Staff applicationPages + dashboard-api routesGoogle SSO, organization email domain
Service tokenCron, queue, admin automationAccess service token (machine-to-machine)
Webhook bypassShopify webhook routes on ingest WorkerBypasses CF Access (external services cannot do Google SSO)
BindingTypePurpose
CF_ACCESS_AUDEnvironment variableAccess application audience tag for JWT validation

A single PlanetScale PostgreSQL database stores all domain and transactional data. Workers connect via Hyperdrive for connection pooling and edge proximity.

PropertyValue
EnginePlanetScale PostgreSQL
ConnectionCloudflare Hyperdrive (env.HYPERDRIVE.connectionString)
ORMDrizzle (PostgreSQL dialect)
Tables153 across 25 modules (including 24 link tables)
Primary keysTEXT with prefixed UIDs (ord_xxx, prd_xxx, mda_xxx)
Migrationsdbmate (planetscale/migrations/YYYYMMDDHHMMSS_description.sql)
FK enforcementNone at DB level (ADR-004) — documented in Drizzle schema only
Stored proceduresNone (ADR-003) — all logic in application code

Module breakdown:

PassModulesTablesFocus
Commerce Core01—13, 1577Products, orders, payments, fulfillment, promotions, regions
Creator Commerce16—2244Publishers, ad servers, memberships, ledger, invoices, disputes, leads
Platform232Macrodata catalog + artifact registry
Links1421Cross-module join tables

See Schema Design for the full table definitions and PlanetScale Constraints for system limits that shape all pipeline operations.

PropertyValue
BindingHYPERDRIVE
FeaturesConnection pooling, optional query caching, edge-routed connections
ConsumersAll three Workers (dashboard-api, platform-api, ingest)
[[hyperdrive]]
binding = "HYPERDRIVE"
id = "your-hyperdrive-id"

These PlanetScale constraints shape all background job design. See PlanetScale Constraints for detailed guidance.

LimitValueDesign response
Rows per query100kCursor-based pagination
Rows per statement100kChunked batch writes
Result size64 MiBSelective column queries
Transaction timeout20sShort, independent transactions
Autocommit timeout900sBounded single statements

All cron triggers execute in the ingest Worker’s scheduled() handler. Each trigger starts a CF Workflow for the actual processing.

ScheduleCron expressionWorkflowScenarioNotes
Daily 06:00 UTC0 6 * * *Shopify Bulk SyncDaily SyncIncremental sync from last watermark
Hourly0 * * * *Measurement RefreshPipelineDuckDB over R2 Iceberg tables
Weekly Sun 03:00 UTC0 3 * * 0Asset Health CheckAsset IngestVerify R2 assets match DB records
# wrangler.toml for ingest Worker
[triggers]
crons = ["0 6 * * *", "0 * * * *", "0 3 * * 0"]

Cron triggers use UTC time. The scheduled() handler dispatches to the appropriate Workflow based on the event.cron expression.