<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sakarikos Kleanthis </title>
    <description>The latest articles on DEV Community by Sakarikos Kleanthis  (@ricogr).</description>
    <link>https://dev.to/ricogr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4064425%2Fb5c34f82-7cc2-4907-bfe2-7bcc657ebc68.png</url>
      <title>DEV Community: Sakarikos Kleanthis </title>
      <link>https://dev.to/ricogr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ricogr"/>
    <language>en</language>
    <item>
      <title>Fixing "Error 1102: Script startup exceeded CPU time limit" on Cloudflare Workers with Next.js</title>
      <dc:creator>Sakarikos Kleanthis </dc:creator>
      <pubDate>Wed, 12 Aug 2026 05:40:25 +0000</pubDate>
      <link>https://dev.to/ricogr/fixing-error-1102-script-startup-exceeded-cpu-time-limit-on-cloudflare-workers-with-nextjs-4l1n</link>
      <guid>https://dev.to/ricogr/fixing-error-1102-script-startup-exceeded-cpu-time-limit-on-cloudflare-workers-with-nextjs-4l1n</guid>
      <description>&lt;h2&gt;
  
  
  Fixing "Error 1102: Script startup exceeded CPU time limit" on Cloudflare Workers with Next.js
&lt;/h2&gt;

&lt;p&gt;If you're deploying a Next.js app to Cloudflare Workers via OpenNext and you've just hit this in your logs or a failed deploy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error 1102: Script startup exceeded CPU time limit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...you're not alone, and it's not really a bug in your app logic. It's almost always caused by one specific, easy-to-miss pattern in how your app gets bundled. Here's what's actually happening, and a free tool that can point you straight at the cause.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this happens
&lt;/h2&gt;

&lt;p&gt;Cloudflare Workers run your code in a V8 isolate. Every time a fresh isolate spins up ("cold start"), it gets a very small CPU budget to finish &lt;em&gt;starting up&lt;/em&gt; — parsing and executing the top level of your script — before it's allowed to actually handle the incoming request.&lt;/p&gt;

&lt;p&gt;Here's the problem: when OpenNext compiles your Next.js app into a single Cloudflare Worker bundle, a lot of setup code that &lt;em&gt;looks&lt;/em&gt; fine in source can end up running at that top level — the module's global scope — instead of inside your actual request handler. Things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This runs on every single cold start, before any request is handled&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;drizzle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If enough of this kind of work piles up at the top level — a database client being constructed, a large i18n translation object, a big Zod validation schema tree — the cold-start CPU budget gets blown before your handler even runs. Cloudflare kills the isolate and you get Error 1102.&lt;/p&gt;

&lt;p&gt;Cloudflare's own docs are direct about the fix: &lt;em&gt;"To reduce startup time, avoid expensive work in global scope. Move initialization logic into your handler."&lt;/em&gt; True, but tracking down exactly &lt;em&gt;which&lt;/em&gt; import or initialization is the culprit inside a fully bundled, minified &lt;code&gt;worker.js&lt;/code&gt; is genuinely tedious — there's no framework tooling that points you at it directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix, in principle
&lt;/h2&gt;

&lt;p&gt;Defer the expensive part into a lazy getter, so it only runs the first time it's actually needed — not on every cold start:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before — runs on every cold start&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;drizzle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// After — runs once, on first actual use&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;_db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;_db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;_db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;drizzle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;_db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple in isolation. The hard part is finding every place in a large, real, minified bundle where this pattern is hiding.&lt;/p&gt;

&lt;h2&gt;
  
  
  A free tool to find it: edge-shake
&lt;/h2&gt;

&lt;p&gt;I built &lt;a href="https://github.com/RiCoGR/edge-shake-optimizer" rel="noopener noreferrer"&gt;&lt;code&gt;edge-shake&lt;/code&gt;&lt;/a&gt;, a small CLI that scans your compiled &lt;code&gt;.open-next/worker.js&lt;/code&gt; and flags exactly this kind of risky top-level code, with an explanation of why it's risky and a suggested fix.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx edge-shake .open-next/worker.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's read-only — it never modifies your files, just tells you what to look at.&lt;/p&gt;

&lt;h3&gt;
  
  
  A real example
&lt;/h3&gt;

&lt;p&gt;Here's &lt;code&gt;edge-shake&lt;/code&gt; running against a genuinely bundled-and-minified Drizzle ORM client construction — the same kind of output esbuild produces when it bundles a Cloudflare Worker, not a hand-written test case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;npx edge-shake fixtures/real-minified-drizzle.js
&lt;span class="go"&gt;edge-shake: found 1 risky top-level pattern(s) in fixtures/real-minified-drizzle.js

[MEDIUM] fixtures/real-minified-drizzle.js:14:24929 — orm-client-construction
  Matched: possible Drizzle ORM client (name mangled by bundler, matched via fingerprint)
  Top-level call taking an "env"-shaped argument, in a file that contains Drizzle ORM's
  runtime fingerprint — this MIGHT be a bundled/minified ORM client construction where the
  original constructor name was renamed by the bundler. This is a lower-confidence heuristic
  match (the fingerprint could belong to unrelated code elsewhere in the bundle) — verify
  manually before treating it as confirmed.
  Suggested fix (not applied):
    If this is client construction, wrap it in a lazy getter so it only runs on first use:
&lt;/span&gt;&lt;span class="gp"&gt;    let _client;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;    function getClient(env) {
&lt;/span&gt;&lt;span class="gp"&gt;      if (!_client) _client = /* this call */;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;      return _client;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;    }

Summary: 1 finding(s) (0 high severity). This is a heuristic diagnostic — "risky", not
"will fail". Run with a paid license to auto-fix allowlisted patterns.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Worth calling out: this is flagged &lt;strong&gt;MEDIUM&lt;/strong&gt;, not HIGH — and that's deliberate, not a bug. Minifiers rename identifiers (in this case, &lt;code&gt;drizzle&lt;/code&gt; became a single mangled letter), so name-based matching alone silently misses real cases after bundling. &lt;code&gt;edge-shake&lt;/code&gt; falls back to checking for string-literal fingerprints that libraries like Drizzle can't avoid shipping (e.g. &lt;code&gt;"drizzle:entityKind"&lt;/code&gt;) even when everything else is renamed — but that's a file-wide co-occurrence signal, not proof, so it's capped at medium severity and clearly labeled as needing manual verification. I'd rather flag something for you to double-check than silently miss it, or silently claim more confidence than the signal actually supports.&lt;/p&gt;

&lt;p&gt;Other patterns it catches: large object/array literals (bloated i18n JSON, static config), large Zod/jose/jsonwebtoken/yup/ajv schema trees, and repeated &lt;code&gt;TextEncoder&lt;/code&gt;/&lt;code&gt;TextDecoder&lt;/code&gt; construction inside a top-level loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx edge-shake .open-next/worker.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it as a post-build step, right after &lt;code&gt;opennextjs-cloudflare build&lt;/code&gt; and before &lt;code&gt;wrangler deploy&lt;/code&gt;. It's free, open source, and read-only.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you want it fixed automatically
&lt;/h2&gt;

&lt;p&gt;The diagnostic is free and always will be. If you'd rather not hand-fix every flagged pattern yourself, there's an optional paid tier that does the rewrite for you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx edge-shake fix .open-next/worker.js &lt;span class="nt"&gt;--write&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's deliberately conservative — it only touches patterns it can fully verify (currently Drizzle, Prisma, and Kysely client construction), and if it can't confidently trace every reference to a binding, it skips that one and tells you why instead of guessing. You can &lt;a href="https://edge-shake.lemonsqueezy.com/checkout/buy/6ec85356-46be-40ff-9104-a6082c816a52" rel="noopener noreferrer"&gt;get a license here&lt;/a&gt; if that's useful to you.&lt;/p&gt;

&lt;p&gt;If you're hitting Error 1102 right now and the free diagnostic doesn't correctly flag your specific case, I'd genuinely like to know — &lt;a href="https://github.com/RiCoGR/edge-shake-optimizer/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt; with what you're seeing.&lt;/p&gt;

</description>
      <category>cloudflare</category>
      <category>nextjs</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
