[{"data":1,"prerenderedAt":125},["ShallowReactive",2],{"work-shopify-otel-kit":3},{"id":4,"title":5,"body":6,"category":87,"challenge":88,"codeSnippet":89,"description":93,"extension":94,"featured":95,"finalScreenshot":96,"gridOrder":97,"isDemo":95,"isDemoURL":80,"liveUrl":97,"meta":98,"mockupImage":99,"navigation":100,"nextProject":101,"order":104,"path":105,"results":97,"schneiderFeatured":95,"schneiderOrder":97,"seo":106,"solution":107,"stem":108,"subtitle":97,"tags":109,"techStack":115,"thumbnail":122,"thumbnailVideo":97,"year":123,"__hash__":124},"works/works/shopify-otel-kit.md","Shopify OTel Kit",{"type":7,"value":8,"toc":79},"minimark",[9,14,18,21,25,32,38,44,50,54,60,66,72,76],[10,11,13],"h2",{"id":12},"the-problem","The Problem",[15,16,17],"p",{},"Shopify app developers fly blind in production. When a merchant reports \"my orders aren't syncing,\" the debugging process involves checking webhook delivery logs in Shopify admin, searching application logs for the relevant shop domain, manually correlating timestamps across systems, and hoping the error message is descriptive enough. There's no way to trace a single webhook from receipt through processing to final outcome.",[15,19,20],{},"This is a solved problem in the broader backend world — OpenTelemetry provides distributed tracing — but nobody has built Shopify-specific instrumentation that understands the platform's unique patterns.",[10,22,24],{"id":23},"architecture","Architecture",[15,26,27,31],{},[28,29,30],"strong",{},"Auto-Instrumentation"," — The library monkey-patches common Shopify app frameworks (Express, Hono, Koa) to automatically create trace spans for webhook handlers. No code changes needed in existing webhook routes.",[15,33,34,37],{},[28,35,36],{},"Shopify Context Propagation"," — Each trace is enriched with Shopify-specific attributes: shop domain, webhook topic, API version, and webhook ID. This enables filtering traces by shop, finding all processing triggered by a specific webhook, or tracking API version migration progress.",[15,39,40,43],{},[28,41,42],{},"API Call Tracing"," — The Shopify API client is instrumented to create child spans for every Admin and Storefront API call. This reveals how many API calls each webhook handler makes, where time is spent, and which calls are failing.",[15,45,46,49],{},[28,47,48],{},"OTLP Export"," — Traces export via OTLP protocol to any compatible backend: Jaeger, Grafana Tempo, Honeycomb, Datadog. Zero vendor lock-in. Configuration is a single environment variable for the collector endpoint.",[10,51,53],{"id":52},"key-technical-decisions","Key Technical Decisions",[15,55,56,59],{},[28,57,58],{},"Why monkey-patching over middleware?"," Middleware requires developers to modify every webhook route. Monkey-patching the framework's route registration means existing apps get instrumentation by adding a single import. The goal is zero-friction adoption.",[15,61,62,65],{},[28,63,64],{},"Why OpenTelemetry over custom tracing?"," OTel is the industry standard with broad backend support. Building on OTel means traces from the Shopify app compose naturally with traces from other services in the merchant's infrastructure.",[15,67,68,71],{},[28,69,70],{},"Why focus on webhooks first?"," Webhooks are the primary failure point in Shopify apps. They arrive asynchronously, have retry semantics that can cause duplicate processing, and their failures are silent (Shopify retries, the app doesn't know it missed one). Tracing webhooks first provides the highest debugging ROI.",[10,73,75],{"id":74},"outcome","Outcome",[15,77,78],{},"The kit has been integrated into 5 production Shopify apps. Mean time to diagnose webhook processing issues dropped from 45 minutes to under 5 minutes. The most impactful discovery: one app was making 23 unnecessary Admin API calls per order webhook, causing rate limiting during sales events.",{"title":80,"searchDepth":81,"depth":81,"links":82},"",2,[83,84,85,86],{"id":12,"depth":81,"text":13},{"id":23,"depth":81,"text":24},{"id":52,"depth":81,"text":53},{"id":74,"depth":81,"text":75},"Observability Toolkit","Shopify apps operate in a distributed environment: webhooks arrive asynchronously, Admin API calls fan out across multiple endpoints, and background jobs process data in queues. When something fails, developers are left grep-ing through logs with no way to trace a customer action across the entire processing chain.",{"language":90,"filename":91,"code":92},"typescript","src/instrumentations/webhook.ts","export function instrumentWebhooks(app: Express) {\n  const original = app.post.bind(app)\n\n  app.post = ((path: string, ...handlers: RequestHandler[]) => {\n    if (!path.startsWith('/webhooks/')) {\n      return original(path, ...handlers)\n    }\n\n    const wrappedHandlers = handlers.map(handler =>\n      async (req: Request, res: Response, next: NextFunction) => {\n        const topic = req.headers['x-shopify-topic'] as string\n        const shop = req.headers['x-shopify-shop-domain'] as string\n\n        const span = tracer.startSpan(`shopify.webhook.${topic}`, {\n          attributes: {\n            'shopify.topic': topic,\n            'shopify.shop': shop,\n            'shopify.webhook_id': req.headers['x-shopify-webhook-id'],\n            'shopify.api_version': req.headers['x-shopify-api-version'],\n          },\n        })\n\n        return context.with(trace.setSpan(context.active(), span), async () => {\n          try {\n            await handler(req, res, next)\n            span.setStatus({ code: SpanStatusCode.OK })\n          } catch (error) {\n            span.setStatus({ code: SpanStatusCode.ERROR })\n            span.recordException(error as Error)\n            throw error\n          } finally {\n            span.end()\n          }\n        })\n      }\n    )\n\n    return original(path, ...wrappedHandlers)\n  }) as typeof app.post\n}\n","A plug-and-play OpenTelemetry instrumentation kit for Shopify apps — automatic tracing of webhook handlers, API calls, and background jobs with zero-config export to any OTel-compatible backend.","md",false,"/images/projects/shopify-otel-kit-final.jpg",null,{},"/images/projects/shopify-otel-kit-mockup.jpg",true,{"title":102,"slug":103},"StockPilot","shopify-agent",9,"/works/shopify-otel-kit",{"title":5,"description":93},"Built an instrumentation library that auto-instruments common Shopify app patterns: webhook receipt and processing, Admin/Storefront API calls, Prisma database queries, and queue job execution. Traces connect the full lifecycle from Shopify webhook to final database write.","works/shopify-otel-kit",[110,111,112,113,114],"OpenTelemetry","Observability","Tracing","Webhooks","Node.js",[116,114,117,118,119,120,121],"OpenTelemetry SDK","Express/Hono","Prisma","Shopify API","OTLP","TypeScript","/images/projects/shopify-otel-kit.jpg","2026","5QVHkrGfjtfryOZblrLASWBfQ3u-xDc2AQ0Qy2RDk9Q",1773700381421]