Been dealing with Bun compatibility bullshit for a while now. Here's the stuff that actually breaks in production, not the theoretical crap in the docs.
Package Resolution Hell
📦 Module Resolution Differences: Node.js vs Bun
Node.js follows CommonJS resolution while Bun uses ESM-first resolution with different fallback behaviors.
The most annoying shit isn't speed - it's packages that work fine in Node but Bun can't find. Happens because Bun's module resolution is different and package authors never test with Bun. Error messages are useless and tell you nothing.
Module resolution differs significantly between runtimes - Node.js uses CommonJS resolution algorithm while Bun implements ESM-first resolution. This creates incompatibilities with packages that rely on Node-specific resolution behaviors. The ECMAScript modules specification doesn't fully cover all edge cases that npm packages exploit.
exports field fucks everything up:
Modern packages use the "exports" field for module resolution. Node and Bun handle this differently:
Error: Cannot resolve "."/lib/index.js" from "."/node_modules/some-package/package.json"
Packages that break:
- @aws-sdk packages: Export maps don't match - AWS SDK v3 compatibility tracking
- Prisma client: Conditional exports fail - Prisma Bun support tracking
- GraphQL tools: Module resolution conflicts - GraphQL-tools compatibility issue
- Styled-components: Babel stuff breaks - styled-components Bun compatibility issue
Quick Fix - Check exports field:
bun pm ls | grep -A5 "."some-package"
cat node_modules/some-package/package.json | grep -A10 '"exports"'
Fix:
// Instead of this (breaks in Bun)
import { something } from 'package-name';
// Do this
import { something } from 'package-name/lib/something.js';
Native Modules Don't Work
⚠️ Native Module Compilation Failures
C++ addons compiled for Node.js N-API don't work with Bun's runtime
Native modules don't work in Bun. These packages compile C++ code that only works with Node. Error messages are garbage and Google won't help.
Why native modules fail: Node.js Native Addons use N-API which is Node-specific. Bun doesn't implement N-API and instead provides Bun's FFI system for native code integration. Node-gyp compilation fails because Bun runtime headers differ from Node.js headers.
Packages that break:
- sharp: Image processing - fails with "."Cannot find module '@img/sharp-libvips'"" - Sharp Bun compatibility status
- bcrypt: Password hashing - compilation errors or segfaults - bcrypt.js Bun tracking issue
- sqlite3: Database driver - use bun:sqlite instead
- node-canvas: Canvas API - no Bun version - Canvas alternatives for Bun
- fsevents: File watching - macOS native code breaks - Bun's built-in file watcher
Works in dev, breaks in prod:
Development on macOS might work with native modules, but production Docker containers will fail:
## This will break in production
FROM oven/bun:1.2-slim
RUN bun install sharp # Fails: no pre-built binaries for Bun runtime
Solution:
- Audit native modules first:
## Find all native modules in your project
find node_modules -name "."*.node"" -exec ls -la {} \;
grep -r "."node-gyp\\|binding\\.gyp"" node_modules/*/package.json
- Use alternatives:
// Instead of bcrypt
import { hash } from 'bun';
// Instead of sqlite3
import { Database } from 'bun:sqlite';
// Instead of sharp
// Use ImageMagick in separate container
- Split services:
## docker-compose.yml
version: '3.8'
services:
api:
image: oven/bun:1.2-slim
command: bun run start
image-processor:
image: node:20-alpine
command: npm run image-service
CPU Architecture Problems
💻 CPU Requirements: AVX2 Instructions
Bun requires modern CPU features that older servers lack, causing immediate crashes
Bun needs newer CPU instructions that older servers don't have. Crashes instantly with useless error messages.
AVX2 requirement details: Bun requires AVX2 CPU instructions for JavaScriptCore's JIT compiler. AWS EC2 instance types and Intel CPU generations affect compatibility. Azure VM sizes have similar limitations with older SKUs.
The Failure Pattern:
./bun: Illegal instruction (core dumped)
Happens on:
- AWS EC2 t2/t3 instances (older Xeon processors)
- Docker on old hosts
- CircleCI, older GitHub Actions runners
- Hardware from before 2013-2014
Check first:
## Check if CPU supports AVX2
grep -o 'avx2' /proc/cpuinfo | head -1
## If no AVX2 support, you're fucked - stick with Node.js
Spent 3 hours debugging this garbage "."Illegal instruction"" error. Turns out the EC2 instance was too old for Bun. Fix: get newer hardware or go back to Node. No software workaround exists.
Memory Leaks (JSC vs V8)
🧠 JavaScript Engine Differences
JavaScriptCore (Bun) vs V8 (Node.js) handle garbage collection and memory management differently
Bun uses JavaScriptCore instead of V8, so memory works differently. Stuff that got cleaned up fine in Node just sits around eating memory.
GC differences matter: JavaScriptCore uses different garbage collection than V8's generational collection. Memory pressure handling differs between engines. JSC heap snapshots use different format than V8 heap profiling.
What leaks memory:
- Closure-heavy code (objects live longer in JSC)
- Event listeners without cleanup
- Large object caching (different GC timing)
- Async iteration (generators behave differently)
Debug Memory Issues:
import { heapStats } from 'bun:jsc';
// Monitor memory every 30 seconds
setInterval(() => {
const stats = heapStats();
const memMB = Math.round(stats.heapSize / 1024 / 1024);
if (memMB > 500) { // Not sure what's normal tbh
console.error(`Memory leak warning: ${memMB}MB heap`);
process.writeHeapSnapshot?.(`leak-${Date.now()}.heapsnapshot`);
}
}, 30000);
Don't do this:
app.get('/api/data', (req, res) => {
const largeData = loadMassiveDataset(); // Leaked in closure
return processRequest(req, (result) => {
res.json(result); // Closure keeps largeData alive
});
});
Do this:
app.get('/api/data', (req, res) => {
const result = processRequestSync(req);
res.json(result);
});
Windows Problems
Windows support exists but comes with weird failures that Linux/macOS devs never see.
File Permission Failures:
## Common Windows error
error: Access denied, EACCES
path: "."node_modules/.bin/some-command"
Why it breaks:
- Windows Defender thinks fast file operations = malware
- NTFS permission issues with symlinks
- PATH length limits (260 chars) break deep node_modules
- PowerShell execution policy blocks scripts
Windows-Specific Fixes:
## 1. Allow PowerShell script execution
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
## 2. Enable long path support (requires admin - good luck)
New-ItemProperty -Path "."HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem"" -Name "."LongPathsEnabled"" -Value 1 -PropertyType DWORD -Force
## 3. Exclude project directory from Windows Defender (sometimes works)
Add-MpPreference -ExclusionPath "."C:\dev\your-project""
Better: Use WSL2
## Install Bun in WSL2 instead
curl -fsSL https://bun.sh/install | bash
Windows support exists but you'll hate your life. Sometimes Windows Defender thinks Bun is malware because it does file operations fast. Use WSL2 to avoid the Windows bullshit.
Latest Shell Crashes
Bun 1.2.21 has new crash when running some shell commands on Windows. Running `cds build --production` causes null pointer panic in shell event loop.
The Pattern:
## This crashes Bun 1.2.21 on Windows
bun run cds build --production
## Stack trace shows
panic: attempt to use null value
* EventLoopHandle.zig:133: topLevelDir
Workaround:
## Use npm run instead
npm run build
## Or downgrade until fixed
bun --version # Check if you're on 1.2.21
This affects SAP CAP framework users, but indicates broader shell command instability. Another reason to have Node.js fallback ready.