Summary
The @tailwindcss/oxide Rust binary used by Tailwind v4 (via @tailwindcss/postcss and @tailwindcss/cli) exhibits unbounded memory growth when processing any input containing @import "tailwindcss";. RSS climbs from ~0 to ~15 GB in 12–60 seconds and is killed by SIGKILL. This is not a Turbopack or Next.js issue — we reproduced the same OOM with the standalone @tailwindcss/cli, which is the official supported build path. The leak is in Oxide itself.
Two independent reproductions, identical OOM signature
Repro A: next build (via @tailwindcss/postcss)
next build (Turbopack) spawns a PostCSS worker that invokes @tailwindcss/postcss, which calls Oxide. Worker RSS grows 30 MB → 15 GB in 56 seconds.
Repro B: @tailwindcss/cli (standalone, no Next.js involved)
The official Tailwind CLI invokes Oxide directly with no Next.js, no Turbopack, no PostCSS, no bundler. RSS grows 0 → 15 GB in 12 seconds, then SIGKILL (exit 137).
This proves the bug is in Oxide, not in Next.js or any integration layer.
Memory profile (Repro B — @tailwindcss/cli)
Host state immediately before compile: 15 GB available RAM, no other Node processes running.
Memory monitor sampled every 2 seconds during tailwindcss -i ./src/app/globals.css -o /tmp/generated.css:
| Elapsed |
Available RAM |
Top process RSS |
Process |
| 0 s |
15108 MB |
276 MB |
next-server (unrelated) |
| 2 s |
14066 MB |
1168 MB |
node (CLI startup) |
| 4 s |
10850 MB |
4386 MB |
node |
| 6 s |
7984 MB |
7239 MB |
node |
| 8 s |
4228 MB |
10975 MB |
node |
| 10 s |
1260 MB |
13974 MB |
node |
| 12 s |
619 MB |
14618 MB |
node |
| 14 s |
63 MB |
15170 MB |
node ← SIGKILL |
Growth rate: ~1.7 GB per 2 seconds — consistent with unbounded AST/scan allocation without release, not a slow leak.
Memory profile (Repro A — next build)
Same host, same globals.css, same 15 GB free before build. Sampled every 5 seconds:
| Elapsed |
Available RAM |
Top process RSS |
Process |
| 0 s |
15433 MB |
30 MB |
caddy (unrelated) |
| 5 s |
14721 MB |
1404 MB |
next-build |
| 20 s |
13057 MB |
2106 MB |
next-build |
| 25 s |
3032 MB |
5674 MB |
node (PostCSS worker spawned) |
| 56 s |
28 MB |
15198 MB |
node ← SIGKILL |
| 65 s |
15271 MB |
275 MB |
next-build (parent retries) |
The PostCSS worker is a child process of next-build:
next-build (v16.3.1)
└─ node ./.next/build/chunks/pool_entry-[turbopack-node]_transforms_postcss_ts_0tp-k2v._.js
The worker file name (transforms_postcss_ts) confirms it is the PostCSS transform pipeline, which calls @tailwindcss/postcss, which calls Oxide.
Reproduction
Repro B (simplest — no Next.js required)
package.json (relevant deps)
{
"devDependencies": {
"tailwindcss": "4.3.3",
"@tailwindcss/cli": "4.3.3"
}
}
globals.css (23 bytes — minimum that triggers the issue)
Command
npx @tailwindcss/cli -i ./globals.css -o ./generated.css
Expected: compile completes, RSS stays bounded (a few hundred MB at most).
Actual: RSS climbs 0 → 15 GB in 12 seconds, killed by SIGKILL (exit 137).
Repro A (Next.js 16 + Turbopack)
src/app/layout.tsx
import './globals.css'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
src/app/globals.css (23 bytes)
postcss.config.js
module.exports = {
plugins: {
"@tailwindcss/postcss": {},
},
}
Command
Actual: PostCSS worker RSS climbs 0 → 15 GB in 56 seconds, killed by SIGKILL.
Environment
| Component |
Version |
| Tailwind CSS |
4.3.3 |
| @tailwindcss/postcss |
4.3.3 |
| @tailwindcss/cli |
4.3.3 |
| @tailwindcss/oxide-linux-x64-gnu |
4.3.3 |
| Node.js |
v22.x (also tested on v20.20.2 — same issue) |
| OS |
Ubuntu 22.04 (kernel 5.15), x86_64, glibc 2.35 |
Diagnostic findings
1. Even a 23-byte input triggers the leak
@import "tailwindcss"; alone is sufficient. Custom CSS, @theme inline, @source directives, and project-specific utility classes are not required. The leak is triggered by Oxide's bootstrap, not by user-authored CSS.
2. Not resource contention
Tested with all production services stopped (pm2 Next.js + 8 systemd microservices), 15 GB available RAM, no other Node processes running. The CLI still OOMed at the same RSS ceiling.
3. Tailwind v3 syntax works on the same machine
Replacing globals.css with v3 syntax (@tailwind base; @tailwind components; @tailwind utilities;) makes the build complete successfully with stable memory (~2 GB peak).
4. Not a musl/glibc binary mismatch
Two Oxide native packages were installed (@tailwindcss/oxide-linux-x64-gnu and @tailwindcss/oxide-linux-x64-musl). Removing the musl binary does not resolve the issue. The host is glibc 2.35.
5. Not a Next.js or Turbopack bug
Repro B reproduces the OOM without any Next.js, Turbopack, or bundler involvement. The leak is in @tailwindcss/oxide itself, invoked through @tailwindcss/cli.
Workaround
We have not found a workaround that allows Tailwind v4 to compile on hosts with less than ~32 GB RAM. Current mitigations:
- Build on a separate machine with ≥32 GB RAM and deploy the artifact (rsync
.next or generated CSS) to production.
- Downgrade to Tailwind v3 — works on the same host with stable memory.
Why we're filing this
This issue makes Tailwind v4 effectively unusable on standard 16 GB VPS hosts — a very common deployment target — regardless of whether the user is using Next.js, Turbopack, or the standalone CLI. The growth pattern (0 → 15 GB in 12 seconds on a 23-byte input) is consistent with an unbounded allocation bug in Oxide's bootstrap path, and we believe it is actionable upstream.
Reproduction repo
A fresh project with npm install tailwindcss @tailwindcss/cli + the 23-byte globals.css reproduces the issue. No application code, no framework, no bundler required.
Tags
area: oxide, area: cli, area: postcss, type: bug, severity: blocker
Summary
The
@tailwindcss/oxideRust binary used by Tailwind v4 (via@tailwindcss/postcssand@tailwindcss/cli) exhibits unbounded memory growth when processing any input containing@import "tailwindcss";. RSS climbs from ~0 to ~15 GB in 12–60 seconds and is killed bySIGKILL. This is not a Turbopack or Next.js issue — we reproduced the same OOM with the standalone@tailwindcss/cli, which is the official supported build path. The leak is in Oxide itself.Two independent reproductions, identical OOM signature
Repro A:
next build(via@tailwindcss/postcss)next build(Turbopack) spawns a PostCSS worker that invokes@tailwindcss/postcss, which calls Oxide. Worker RSS grows 30 MB → 15 GB in 56 seconds.Repro B:
@tailwindcss/cli(standalone, no Next.js involved)The official Tailwind CLI invokes Oxide directly with no Next.js, no Turbopack, no PostCSS, no bundler. RSS grows 0 → 15 GB in 12 seconds, then
SIGKILL(exit 137).This proves the bug is in Oxide, not in Next.js or any integration layer.
Memory profile (Repro B —
@tailwindcss/cli)Host state immediately before compile: 15 GB available RAM, no other Node processes running.
Memory monitor sampled every 2 seconds during
tailwindcss -i ./src/app/globals.css -o /tmp/generated.css:Growth rate: ~1.7 GB per 2 seconds — consistent with unbounded AST/scan allocation without release, not a slow leak.
Memory profile (Repro A —
next build)Same host, same
globals.css, same 15 GB free before build. Sampled every 5 seconds:The PostCSS worker is a child process of
next-build:The worker file name (
transforms_postcss_ts) confirms it is the PostCSS transform pipeline, which calls@tailwindcss/postcss, which calls Oxide.Reproduction
Repro B (simplest — no Next.js required)
package.json(relevant deps){ "devDependencies": { "tailwindcss": "4.3.3", "@tailwindcss/cli": "4.3.3" } }globals.css(23 bytes — minimum that triggers the issue)Command
Expected: compile completes, RSS stays bounded (a few hundred MB at most).
Actual: RSS climbs 0 → 15 GB in 12 seconds, killed by
SIGKILL(exit 137).Repro A (Next.js 16 + Turbopack)
src/app/layout.tsxsrc/app/globals.css(23 bytes)postcss.config.jsCommand
Actual: PostCSS worker RSS climbs 0 → 15 GB in 56 seconds, killed by
SIGKILL.Environment
Diagnostic findings
1. Even a 23-byte input triggers the leak
@import "tailwindcss";alone is sufficient. Custom CSS,@theme inline,@sourcedirectives, and project-specific utility classes are not required. The leak is triggered by Oxide's bootstrap, not by user-authored CSS.2. Not resource contention
Tested with all production services stopped (pm2 Next.js + 8 systemd microservices), 15 GB available RAM, no other Node processes running. The CLI still OOMed at the same RSS ceiling.
3. Tailwind v3 syntax works on the same machine
Replacing
globals.csswith v3 syntax (@tailwind base; @tailwind components; @tailwind utilities;) makes the build complete successfully with stable memory (~2 GB peak).4. Not a musl/glibc binary mismatch
Two Oxide native packages were installed (
@tailwindcss/oxide-linux-x64-gnuand@tailwindcss/oxide-linux-x64-musl). Removing the musl binary does not resolve the issue. The host is glibc 2.35.5. Not a Next.js or Turbopack bug
Repro B reproduces the OOM without any Next.js, Turbopack, or bundler involvement. The leak is in
@tailwindcss/oxideitself, invoked through@tailwindcss/cli.Workaround
We have not found a workaround that allows Tailwind v4 to compile on hosts with less than ~32 GB RAM. Current mitigations:
.nextor generated CSS) to production.Why we're filing this
This issue makes Tailwind v4 effectively unusable on standard 16 GB VPS hosts — a very common deployment target — regardless of whether the user is using Next.js, Turbopack, or the standalone CLI. The growth pattern (0 → 15 GB in 12 seconds on a 23-byte input) is consistent with an unbounded allocation bug in Oxide's bootstrap path, and we believe it is actionable upstream.
Reproduction repo
A fresh project with
npm install tailwindcss @tailwindcss/cli+ the 23-byteglobals.cssreproduces the issue. No application code, no framework, no bundler required.Tags
area: oxide,area: cli,area: postcss,type: bug,severity: blocker