<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/an-llm-adapter-pattern-for-cloudflare-workers-aiijgoqdd" -->

---
title: An LLM adapter pattern for Cloudflare Workers | daily.dev
description: A practical adapter pattern for integrating LLM providers into Cloudflare Workers, where heavy vendor SDKs often fail due to the limited workerd runtime. The...
canonical: https://daily.dev/posts/an-llm-adapter-pattern-for-cloudflare-workers-aiijgoqdd
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: An LLM adapter pattern for Cloudflare Workers | daily.dev
og:description: A practical adapter pattern for integrating LLM providers into Cloudflare Workers, where heavy vendor SDKs often fail due to the limited workerd runtime. The...
og:url: https://daily.dev/posts/an-llm-adapter-pattern-for-cloudflare-workers-aiijgoqdd
og:image: https://api.daily.dev/og/posts/AIIjgOQDD.png
og:image:alt: An LLM adapter pattern for Cloudflare Workers
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# An LLM adapter pattern for Cloudflare Workers

**[Flavio Copes](https://daily.dev/sources/flaviocopes)** · 3 min read · 0 upvotes · 0 comments

## Summary

A practical adapter pattern for integrating LLM providers into Cloudflare Workers, where heavy vendor SDKs often fail due to the limited workerd runtime. The approach defines a single interface (e.g., completeText, generateRationale), implements it with a raw fetch-based OpenAI-compatible client, and selects providers via environment variables. Graceful degradation returns null when no adapter is configured, keeping the app functional. Additional tips cover defensive JSON parsing (stripping markdown fences, validating with Zod), KV caching of responses, and isolating vendor details in a single module so routes never import SDK packages directly.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://flaviocopes.com/llm-adapter-pattern>

## Questions this post answers

### Why can't I use the OpenAI or Anthropic Node SDK inside a Cloudflare Worker?

Cloudflare Workers run on the workerd runtime, which exposes fetch, crypto, and TextEncoder but not the full Node API surface that vendor SDKs like @openai/sdk or @anthropic-ai/sdk expect, so those heavy SDKs often fail to execute inside workerd. The fix is to call the provider's REST endpoint directly with fetch instead of importing the SDK.

_Developers hitting SDK compatibility errors on Workers can find pattern write-ups like this through daily.dev._

### How do I make my Cloudflare Worker support multiple LLM providers like OpenAI, Groq, and OpenRouter without rewriting my routes?

Define one adapter interface with a small set of methods (for example completeText and generateRationale), then implement a single fetch-based function per provider that hits an OpenAI-compatible chat completions endpoint, only changing the baseUrl for OpenRouter, Groq, or Cloudflare AI Gateway. Select the active adapter centrally based on an environment variable like LLM_PROVIDER, so routes never import a vendor SDK directly.

_Teams comparing LLM providers for their stack can track adapter patterns like this on daily.dev._

### What should my app do when an LLM call fails or no provider is configured in production?

The feature should hide rather than crash: if getAdapter() returns null because no provider is configured, return null immediately, and wrap the actual LLM call in a try/catch that logs the error and also returns null on failure. Non-LLM parts of the page, such as data computed by a separate rules engine, should keep working regardless of LLM availability.

_daily.dev helps developers building resilient LLM-backed features stay current on graceful-degradation patterns._

## Similar posts on daily.dev

- [Cloudflare Workers AI: run LLMs without API keys](https://daily.dev/posts/cloudflare-workers-ai-run-llms-without-api-keys-sxc7e3lma) · Flavio Copes · 1 upvotes · 0 comments
- [LLM Router Pattern \(2026\): Model Routing, Fallbacks, Cost Control](https://daily.dev/posts/llm-router-pattern-2026-model-routing-fallbacks-cost-control-8txalf5nf) · Alex CloudStar · 1 upvotes · 0 comments
- [Integrating LLM APIs: A Practical Guide for Developers](https://daily.dev/posts/integrating-llm-apis-a-practical-guide-for-developers-vkx35bykm) · Redis · 0 upvotes · 0 comments
- [Taming the generative AI back end](https://daily.dev/posts/taming-the-generative-ai-back-end-trqdratyl) · InfoWorld · 0 upvotes · 0 comments
- [Making LLMs boring: From chatbots to semantic processors](https://daily.dev/posts/making-llms-boring-from-chatbots-to-semantic-processors-9trmmy1ca) · Red Hat Developer · 1 upvotes · 0 comments

---

Tags: [#javascript](https://daily.dev/tags/javascript), [#llm](https://daily.dev/tags/llm), [#openai](https://daily.dev/tags/openai), [#cloudflare](https://daily.dev/tags/cloudflare)

[View this post on daily.dev](https://daily.dev/posts/an-llm-adapter-pattern-for-cloudflare-workers-aiijgoqdd)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"An LLM adapter pattern for Cloudflare Workers","url":"https://daily.dev/posts/an-llm-adapter-pattern-for-cloudflare-workers-aiijgoqdd","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/an-llm-adapter-pattern-for-cloudflare-workers-aiijgoqdd"},"datePublished":"2026-07-24T07:46:48.417Z","dateModified":"2026-09-13T21:43:21.444Z","description":"A practical adapter pattern for integrating LLM providers into Cloudflare Workers, where heavy vendor SDKs often fail due to the limited workerd runtime. The...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/907c6c028f107fad7d0379f1571dde35?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/907c6c028f107fad7d0379f1571dde35?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Flavio Copes","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Flavio Copes","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/1f2dbd275797411bbd37bfdaaf0951a9","url":"https://daily.dev/sources/flaviocopes"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/an-llm-adapter-pattern-for-cloudflare-workers-aiijgoqdd","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"javascript,llm,openai,cloudflare","timeRequired":"PT3M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Flavio Copes","item":"https://daily.dev/sources/flaviocopes"},{"@type":"ListItem","position":3,"name":"An LLM adapter pattern for Cloudflare Workers"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/an-llm-adapter-pattern-for-cloudflare-workers-aiijgoqdd#faq","mainEntity":[{"@type":"Question","name":"Why can't I use the OpenAI or Anthropic Node SDK inside a Cloudflare Worker?","acceptedAnswer":{"@type":"Answer","text":"Cloudflare Workers run on the workerd runtime, which exposes fetch, crypto, and TextEncoder but not the full Node API surface that vendor SDKs like @openai/sdk or @anthropic-ai/sdk expect, so those heavy SDKs often fail to execute inside workerd. The fix is to call the provider's REST endpoint directly with fetch instead of importing the SDK. Developers hitting SDK compatibility errors on Workers can find pattern write-ups like this through daily.dev."}},{"@type":"Question","name":"How do I make my Cloudflare Worker support multiple LLM providers like OpenAI, Groq, and OpenRouter without rewriting my routes?","acceptedAnswer":{"@type":"Answer","text":"Define one adapter interface with a small set of methods (for example completeText and generateRationale), then implement a single fetch-based function per provider that hits an OpenAI-compatible chat completions endpoint, only changing the baseUrl for OpenRouter, Groq, or Cloudflare AI Gateway. Select the active adapter centrally based on an environment variable like LLM_PROVIDER, so routes never import a vendor SDK directly. Teams comparing LLM providers for their stack can track adapter patterns like this on daily.dev."}},{"@type":"Question","name":"What should my app do when an LLM call fails or no provider is configured in production?","acceptedAnswer":{"@type":"Answer","text":"The feature should hide rather than crash: if getAdapter() returns null because no provider is configured, return null immediately, and wrap the actual LLM call in a try/catch that logs the error and also returns null on failure. Non-LLM parts of the page, such as data computed by a separate rules engine, should keep working regardless of LLM availability. daily.dev helps developers building resilient LLM-backed features stay current on graceful-degradation patterns."}}]}
```

