Tom Sailors
· Refreshed
Brief · Anonymized case study

Autonomous Monitoring Agent for Shopify Operations

Build a monitoring agent that watches four critical system layers: compute health (Heroku dyno response times and error rates), external integrations (carrier uptime checks), data freshness (catalog sync windows), and financial accuracy (tax sync drift). Each monitor runs on a schedule, tests its system with a live request, and posts to Slack when thresholds breach. The pattern handles both infrastructure and business-logic failures in one agent.

A Shopify store running on a Heroku infrastructure stack with third-party integrations across shipping, inventory, and tax compliance needed continuous visibility into system health. Critical systems—dyno performance, carrier API endpoints, product sync pipelines, and tax calculation consistency—had no centralized alerting, creating operational blind spots where failures went undetected until customer impact occurred.
Four pieces
Operations

Dyno Health Monitor

Pings Heroku dynos every few minutes, checks response times and error rates, alerts Slack if a dyno is slow or crashing.

Monitoring service + Slack webhook
Shipping

Carrier API Uptime Check

Tests carrier integrations (ShipEngine, FedEx, UPS) on schedule, confirms rate lookups and label generation work, flags when a carrier goes offline.

Health-check worker + Slack webhook
Admin GraphQL explorer graphql
# Admin GraphQL — test fulfillment orders to confirm carrier availability
query TestCarrierRates {
  fulfillmentOrders(first: 10) {
    edges {
      node {
        id
        status
        lineItems(first: 5) {
          edges {
            node {
              id
              lineItem {
                quantity
              }
            }
          }
        }
        deliveryMethod {
          id
        }
      }
    }
  }
}
Removed status argument (not supported on fulfillmentOrders); nested quantity under lineItem to access the FulfillmentLineItem parent.
Inventory

Catalog Freshness Check

Compares product counts, metafield values, and inventory timestamps in the Shopify store to the source of truth, alerts if a sync hasn't run or data looks stale.

Scheduled worker + Slack webhook
Admin GraphQL explorer graphql
# Admin GraphQL — check product sync freshness
query CheckCatalogFreshness {
  products(first: 1, query: "updated_at:>2024-01-01", sortKey: UPDATED_AT, reverse: true) {
    edges {
      node {
        id
        handle
        updatedAt
        metafield(namespace: "custom", key: "last_sync") {
          value
        }
      }
    }
  }
}
# On the monitoring worker: compare updatedAt timestamps against current time.
# If no products updated in the last 24h (or your interval), fire a Slack alert.
Set the timestamp threshold and sync window in monitoring config; adjust 'last_sync' namespace/key to match actual metafield.
Operations

Tax Sync Drift Detector

Watches tax records and rates in the tax system (TaxJar, Vertex, Avalara) against Shopify order tax data, alerts if calculations diverge or a sync worker fails.

Drift-check worker + Slack webhook
Admin GraphQL explorer graphql
# Admin GraphQL — sample recent orders for tax audit
query TaxDriftAudit {
  orders(first: 10, query: "created_at:>2024-01-15", sortKey: CREATED_AT, reverse: true) {
    edges {
      node {
        id
        name
        createdAt
        totalTaxSet {
          shopMoney {
            amount
            currencyCode
          }
        }
        lineItems(first: 50) {
          edges {
            node {
              id
              sku
              taxLines {
                title
                ratePercentage
                price
              }
            }
          }
        }
      }
    }
  }
}
# On the worker: fetch the same orders from TaxJar/Vertex and compare totalTaxSet amounts.
Removed selection set from taxLines.price—it is a scalar Money type, not an object. Price is already a decimal string.

Got a similar problem?

Sketch your build in 30 seconds — voice, type, or attach a screenshot.

Sketch the build →