-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Description
What version of Bun is running?
1.3.9
What platform is your computer?
Linux x86_64 (Docker: oven/bun:1.3.9)
What steps can reproduce the bug?
git clone https://github.com/slucascosta/bun-mtls-memory-leak.git
cd bun-mtls-memory-leak
docker compose up --build3 tests run against a local HTTPS server:
- test-http -- HTTPS fetch without client cert (control)
- test-mtls -- HTTPS fetch with client cert via
tlsoption (leaks) - test-node-mtls -- Same as 2 but in Node.js 24 (control)
Each test: 3 rounds x 10,000 requests @ 100 req/s, with Bun.gc(true) + 5s pause between rounds.
Minimal reproduction
import fs from "fs";
const cert = fs.readFileSync("data/certs/server.crt", "utf-8");
const key = fs.readFileSync("data/certs/server.key", "utf-8");
for (let round = 1; round <= 3; round++) {
for (let i = 0; i < 10_000; i++) {
try {
const res = await fetch("https://localhost:8443/", {
tls: { cert, key, rejectUnauthorized: false },
});
await res.text();
} catch {}
}
Bun.gc(true);
await Bun.sleep(5000);
const m = process.memoryUsage();
console.log(`Round ${round}: RSS=${Math.round(m.rss / 1024 / 1024)}MB`);
}
// RSS grows ~35MB per round and is never reclaimed.What is the expected behavior?
RSS should remain stable across rounds. Certificates are loaded once, response bodies are fully consumed, and GC is explicitly called between rounds.
What do you see instead?
RSS grows linearly with each fetch() that uses the tls option and is never reclaimed.
| Test | Runtime | Requests | RSS growth | Leak? |
|---|---|---|---|---|
| HTTPS (no client cert) | Bun 1.3.9 | 30,000 | +20MB | No |
HTTPS + client cert (tls) |
Bun 1.3.9 | 30,000 | +109MB | Yes |
| HTTPS + client cert | Node.js 24.13.1 | 30,000 | +22MB | No |
- The only difference between test-http and test-mtls is
{ tls: { cert, key } }in fetch options - Heap stays at 1MB -- the leak is in native memory, not JS heap
- The leak is linear: ~3.6KB/request (~36MB per 10k requests)
- Node.js with the same workload does not leak
Suspected root cause
Each fetch() call with a tls option appears to allocate a new native SSL context that is never freed. Consistent with unreleased BoringSSL SSL_CTX or SSL objects.
Related issues
- Possible memory leak #16503 -- Possible memory leak (SSL connection suspected)
- mTLS Implementation Issues #16254 -- mTLS implementation issues
- Type error with
fetchandtls-Option #13599 -- Type error withfetchandtlsoption
Related fixes (may not cover this scenario)
- fix(us): memory leak when getting x509 certificate stores #17781 -- Fix memory leak in
us_get_default_ca_store(x509 ref counting) - fix(us): memory leak when getting root certificate #16073 -- Fix memory leak when getting root certificate for HTTPS server
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels