Memory leak in `@tailwindcss/oxide` — RSS grows 0 → 15 GB in 12 seconds, reproduces with both `next build` and `@tailwindcss/cli` standalone (Tailwind v4.3.3)
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 45/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Domain
- build-system, cli, performance
Research direction
Start with the minimal globals.css reproduction and run npx @tailwindcss/cli -i ./globals.css -o ./generated.css; inspect the @tailwindcss/oxide bootstrap path reached by the standalone CLI. Compare its behavior with the documented RSS growth and confirm that the compile completes with bounded memory on the 23-byte input.
Written by the indexing model from the issue text.
Description
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)
@import "tailwindcss";
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)
@import "tailwindcss";
postcss.config.js
module.exports = {
plugins: {
"@tailwindcss/postcss": {},
},
}
Command
npx next build
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
.nextor 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
- Dominant language
- TypeScript
- Stars
- 97.9k
- Forks
- 8.9k
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 24
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from tailwindlabs/tailwindcss
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
tailwindlabs/tailwindcss#20491 · 1 reaction ·
Maintainers usually reply within 1 day
-
Scanner `globs` walks gitignored directories (files pass respects .gitignore, globs pass does not)May be free again @akasakariko claimed this 18 days ago, and no pull request is open. Open
Difficulty 3/5 1-2 days Newbie friendliness 58/100
tailwindlabs/tailwindcss#20533 · 3 comments ·
Maintainers usually reply within 1 day
-
Source detection ignores `core.excludesFile`, so globally-ignored directories are scanned (reproduction for #19801)Possibly taken @Lukecele claimed this 23 days ago. Open
Difficulty 3/5 1-2 days Newbie friendliness 65/100
tailwindlabs/tailwindcss#20509 ·
Maintainers usually reply within 1 day
-
@tailwindcss/vite: cached Root.compiler pins the build's plugin context, keeping the finished bundle alive (multi-GB RSS in Astro SSG)Possibly taken @lazerg claimed this 29 days ago. Open
Difficulty 4/5 3-5 days Newbie friendliness 68/100
tailwindlabs/tailwindcss#20501 · 4 comments ·
Maintainers usually reply within 1 day
-
Oxide 4.3.3: Windows access violation after scanning in a Node worker and unloading the addonPossibly taken @bompus claimed this 42 days ago. Open
Difficulty 4/5 3-5 days Newbie friendliness 25/100
tailwindlabs/tailwindcss#20470 ·
Maintainers usually reply within 1 day
All issues in tailwindlabs/tailwindcss
Similar issues
-
area: app type: bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
ExpidetGames/code-reviewer#585 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 83/100
module-federation/core#5205 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
LanternOps/breeze#9392 · 1 comment ·
Maintainers usually reply within 1 day
-
engine-rs P3 review-deferral wasm
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
maniator/verticopolis#1154 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day