---
title: "Bunqueue Performance Benchmarks: 286K Ops/Sec on Bun"
description: Bunqueue benchmarks show 286K ops/sec embedded, 149K ops/sec TCP. Real-world throughput tests at 1K to 50K job scales on Bun runtime.
head:
  - tag: meta
    attrs:
      property: og:image
      content: https://bunqueue.dev/og/benchmarks.png
---

import { Tabs, TabItem, Card, CardGrid, Aside, Code } from '@astrojs/starlight/components';

bunqueue supports two deployment modes: **Embedded** (direct SQLite) and **TCP** (network + SQLite). This page shows real benchmark results comparing both modes at scale.

<Aside type="tip">
The only honest benchmark is one you run on your own hardware. Clone the repo and run `bun run bench/comprehensive.ts` to verify these results.
</Aside>

## Summary

<CardGrid>
  <Card title="Embedded Mode" icon="rocket">
    **Up to 286K ops/sec**

    Direct SQLite access, zero network overhead
  </Card>
  <Card title="TCP Mode" icon="laptop">
    **Up to 149K ops/sec**

    Network client/server for distributed systems
  </Card>
  <Card title="Embedded Advantage" icon="star">
    **2-4x Faster**

    Depending on operation type
  </Card>
  <Card title="Scale Tested" icon="open-book">
    **50,000 Jobs**

    Verified at multiple scales
  </Card>
</CardGrid>

---

## Embedded Mode Results

Embedded mode uses direct SQLite access with no network overhead. Ideal for single-process applications.

<div style={{ textAlign: 'center', margin: '2rem 0' }}>
  <img
    src="https://quickchart.io/chart?c={type:'bar',data:{labels:['1K','5K','10K','50K'],datasets:[{label:'Push',data:[86248,187256,177098,204913],backgroundColor:'rgba(236,72,153,0.85)'},{label:'Bulk Push',data:[221365,278587,279640,286616],backgroundColor:'rgba(168,85,247,0.85)'},{label:'Process',data:[47538,64716,77713,74772],backgroundColor:'rgba(59,130,246,0.85)'}]},options:{plugins:{title:{display:true,text:'Embedded Mode Throughput (ops/sec)',font:{size:18,weight:'bold'}},legend:{position:'bottom'}},scales:{y:{beginAtZero:true,title:{display:true,text:'Operations/sec'},grid:{color:'rgba(0,0,0,0.1)'}},x:{title:{display:true,text:'Job Count'},grid:{display:false}}}}}&width=650&height=400&backgroundColor=white"
    alt="Embedded mode throughput chart"
    style={{ maxWidth: '650px', width: '100%', borderRadius: '12px', boxShadow: '0 4px 6px -1px rgba(0,0,0,0.1)' }}
  />
</div>

| Scale | Push | Bulk Push | Process |
|-------|------|-----------|---------|
| **1,000** | 86,248 ops/sec | 221,365 ops/sec | 47,538 ops/sec |
| **5,000** | 187,256 ops/sec | 278,587 ops/sec | 64,716 ops/sec |
| **10,000** | 177,098 ops/sec | 279,640 ops/sec | 77,713 ops/sec |
| **50,000** | 204,913 ops/sec | 286,616 ops/sec | 74,772 ops/sec |

<Aside>
Embedded mode shows consistent performance scaling. Bulk push reaches nearly **287K ops/sec** at 50K jobs.
</Aside>

---

## TCP Mode Results

TCP mode connects clients to a bunqueue server over the network. Required for distributed systems with multiple client processes.

<div style={{ textAlign: 'center', margin: '2rem 0' }}>
  <img
    src="https://quickchart.io/chart?c={type:'bar',data:{labels:['1K','5K','10K','50K'],datasets:[{label:'Push',data:[28633,49284,54562,51827],backgroundColor:'rgba(236,72,153,0.85)'},{label:'Bulk Push',data:[96635,142152,149218,131897],backgroundColor:'rgba(168,85,247,0.85)'},{label:'Process',data:[20195,34098,34679,32544],backgroundColor:'rgba(59,130,246,0.85)'}]},options:{plugins:{title:{display:true,text:'TCP Mode Throughput (ops/sec)',font:{size:18,weight:'bold'}},legend:{position:'bottom'}},scales:{y:{beginAtZero:true,title:{display:true,text:'Operations/sec'},grid:{color:'rgba(0,0,0,0.1)'}},x:{title:{display:true,text:'Job Count'},grid:{display:false}}}}}&width=650&height=400&backgroundColor=white"
    alt="TCP mode throughput chart"
    style={{ maxWidth: '650px', width: '100%', borderRadius: '12px', boxShadow: '0 4px 6px -1px rgba(0,0,0,0.1)' }}
  />
</div>

| Scale | Push | Bulk Push | Process |
|-------|------|-----------|---------|
| **1,000** | 28,633 ops/sec | 96,635 ops/sec | 20,195 ops/sec |
| **5,000** | 49,284 ops/sec | 142,152 ops/sec | 34,098 ops/sec |
| **10,000** | 54,562 ops/sec | 149,218 ops/sec | 34,679 ops/sec |
| **50,000** | 51,827 ops/sec | 131,897 ops/sec | 32,544 ops/sec |

<Aside>
TCP mode with pipelining achieves **149K ops/sec** bulk push at 10K jobs. Network overhead is amortized with connection pooling (32 connections).
</Aside>

---

## Embedded vs TCP Comparison

How much faster is Embedded mode compared to TCP mode?

<div style={{ textAlign: 'center', margin: '2rem 0' }}>
  <img
    src="https://quickchart.io/chart?c={type:'bar',data:{labels:['1K Jobs','5K Jobs','10K Jobs','50K Jobs'],datasets:[{label:'Push',data:[3.0,3.8,3.2,4.0],backgroundColor:'rgba(236,72,153,0.85)'},{label:'Bulk Push',data:[2.3,2.0,1.9,2.2],backgroundColor:'rgba(168,85,247,0.85)'},{label:'Process',data:[2.4,1.9,2.2,2.3],backgroundColor:'rgba(59,130,246,0.85)'}]},options:{plugins:{title:{display:true,text:'Embedded vs TCP Speedup (times faster)',font:{size:18,weight:'bold'}},legend:{position:'bottom'}},scales:{y:{beginAtZero:true,title:{display:true,text:'Speedup (x times)'},grid:{color:'rgba(0,0,0,0.1)'}},x:{grid:{display:false}}}}}&width=650&height=400&backgroundColor=white"
    alt="Embedded vs TCP comparison chart"
    style={{ maxWidth: '650px', width: '100%', borderRadius: '12px', boxShadow: '0 4px 6px -1px rgba(0,0,0,0.1)' }}
  />
</div>

| Scale | Push | Bulk Push | Process |
|-------|------|-----------|---------|
| **1,000** | 3.0x faster | 2.3x faster | 2.4x faster |
| **5,000** | 3.8x faster | 2.0x faster | 1.9x faster |
| **10,000** | 3.2x faster | 1.9x faster | 2.2x faster |
| **50,000** | 4.0x faster | 2.2x faster | 2.3x faster |

<Aside type="tip">
Embedded mode is **2-4x faster** than TCP mode across all operations and scales. Use embedded mode when your workers run in the same process as the queue.
</Aside>

---

## Peak Performance Summary

<div style={{ textAlign: 'center', margin: '2rem 0' }}>
  <img
    src="https://quickchart.io/chart?c={type:'bar',data:{labels:['Push','Bulk Push','Process'],datasets:[{label:'Embedded',data:[204913,286616,77713],backgroundColor:'rgba(236,72,153,0.85)'},{label:'TCP',data:[54562,149218,34679],backgroundColor:'rgba(59,130,246,0.85)'}]},options:{plugins:{title:{display:true,text:'Peak Throughput Comparison (ops/sec)',font:{size:18,weight:'bold'}},legend:{position:'bottom'}},scales:{y:{beginAtZero:true,title:{display:true,text:'Operations/sec'},grid:{color:'rgba(0,0,0,0.1)'}},x:{grid:{display:false}}}}}&width=600&height=400&backgroundColor=white"
    alt="Peak throughput comparison chart"
    style={{ maxWidth: '600px', width: '100%', borderRadius: '12px', boxShadow: '0 4px 6px -1px rgba(0,0,0,0.1)' }}
  />
</div>

| Operation | Embedded Mode | TCP Mode |
|-----------|--------------|----------|
| **Push** (peak) | 204,913 ops/sec | 54,562 ops/sec |
| **Bulk Push** (peak) | 286,616 ops/sec | 149,218 ops/sec |
| **Process** (peak) | 77,713 ops/sec | 34,679 ops/sec |

---

## Benchmark Methodology

The benchmark tests three operations at four different scales (1K, 5K, 10K, 50K jobs):

### 1. Push Test
Sequential push of individual jobs to measure single-job insertion speed.

```typescript
for (let i = 0; i < scale; i++) {
  await queue.add('job', PAYLOAD);
}
```

### 2. Bulk Push Test
Push jobs in batches of 100 to measure bulk insertion efficiency.

```typescript
const jobs = Array.from({ length: 100 }, (_, i) => ({
  name: 'bulk-job',
  data: { ...PAYLOAD, i },
}));

for (let i = 0; i < scale / 100; i++) {
  await queue.addBulk(jobs);
}
```

### 3. Process Test
Push jobs in parallel batches of 500, then process them with 10 concurrent workers.

```typescript
// Push in parallel batches
for (let i = 0; i < scale; i += 500) {
  const promises = [];
  for (let j = 0; j < Math.min(500, scale - i); j++) {
    promises.push(queue.add('job', PAYLOAD));
  }
  await Promise.all(promises);
}

// Wait for all to complete
while (processed < scale) {
  await sleep(5);
}
```

---

## Run the Benchmark

The benchmark source code is available at [`bench/comprehensive.ts`](https://github.com/egeominotti/bunqueue/blob/main/bench/comprehensive.ts).

```bash
# Clone the repository
git clone https://github.com/egeominotti/bunqueue.git
cd bunqueue
bun install

# Start the bunqueue server (for TCP tests)
bun run start &

# Run the comprehensive benchmark
bun run bench/comprehensive.ts
```

### Expected Output

```
═══════════════════════════════════════════════════════════════
         bunqueue Comprehensive Benchmark
         Embedded vs TCP Mode
═══════════════════════════════════════════════════════════════

Scales: 1,000, 5,000, 10,000, 50,000 jobs
Bulk size: 100
Concurrency: 10
Payload: 111 bytes

✓ TCP server connected (port 6789)

📦 EMBEDDED MODE (Direct SQLite)
══════════════════════════════════════════════════

🔄 Testing 1,000 jobs...
  Push: 86,248 ops/sec
  Bulk Push: 221,365 ops/sec
  Process: 47,538 ops/sec

...

📊 EMBEDDED MODE RESULTS

┌──────────┬────────────────┬────────────────┬────────────────┐
│ Scale    │ Push (ops/s)   │ Bulk (ops/s)   │ Process (ops/s)│
├──────────┼────────────────┼────────────────┼────────────────┤
│    1,000 │       86,248   │      221,365   │       47,538   │
│    5,000 │      187,256   │      278,587   │       64,716   │
│   10,000 │      177,098   │      279,640   │       77,713   │
│   50,000 │      204,913   │      286,616   │       74,772   │
└──────────┴────────────────┴────────────────┴────────────────┘

📈 EMBEDDED vs TCP (Embedded is X times faster)

┌──────────┬────────────────┬────────────────┬────────────────┐
│ Scale    │ Push           │ Bulk           │ Process        │
├──────────┼────────────────┼────────────────┼────────────────┤
│    1,000 │         3.0x   │         2.3x   │         2.4x   │
│    5,000 │         3.8x   │         2.0x   │         1.9x   │
│   10,000 │         3.2x   │         1.9x   │         2.2x   │
│   50,000 │         4.0x   │         2.2x   │         2.3x   │
└──────────┴────────────────┴────────────────┴────────────────┘
```

---

## When to Use Each Mode

<CardGrid>
  <Card title="Embedded Mode" icon="rocket">
    **Best for single-process apps**

    - Microservices
    - CLI tools
    - Edge functions
    - Serverless
  </Card>
  <Card title="TCP Mode" icon="laptop">
    **Best for distributed systems**

    - Multiple worker processes
    - Separate producer/consumer
    - Horizontal scaling
    - Remote workers
  </Card>
</CardGrid>

---

## Why bunqueue is Fast

<CardGrid>
  <Card title="SQLite WAL Mode" icon="seti:db">
    Concurrent reads/writes with memory-mapped I/O via Bun's native FFI bindings.
  </Card>
  <Card title="Auto Sharding" icon="puzzle">
    Auto-detected from CPU cores (power of 2, max 64). Minimizes lock contention.
  </Card>
  <Card title="TCP Pipelining" icon="rocket">
    Multiple commands in flight per connection with reqId-based response matching.
  </Card>
  <Card title="Efficient Structures" icon="seti:config">
    4-ary MinHeap for O(log4 n) priority queues. Skip lists for temporal indexing. LRU caches.
  </Card>
</CardGrid>

---

## Benchmark Environment

**Hardware:**
- Mac Studio, Apple M1 Max
- 32GB RAM
- SSD storage

**Software:**
- macOS Tahoe
- Bun 1.3.8

**Configuration:**
- Scales: 1,000, 5,000, 10,000, 50,000 jobs
- Bulk size: 100 jobs per batch
- Concurrency: 10 workers
- Payload: 111 bytes
- Connection pool: 32 connections (TCP mode)

---

## Dependency Chain Latency

Jobs with dependencies (`dependsOn`, `FlowProducer`, parent-child workflows) benefit from event-driven dependency resolution via microtask coalescing, replacing the previous 100ms polling interval.

### Before (polling 100ms via setInterval)

| Scenario | Avg | P50 | P95 | P99 |
|----------|-----|-----|-----|-----|
| **Single dep (A&rarr;B)** | 100.09ms | 100.05ms | 101.91ms | 103.90ms |
| **Chain dep (4 levels)** | 300.83ms | 300.43ms | 304.19ms | 306.72ms |
| **Fan-out (1&rarr;5)** | 100.21ms | 100.11ms | 101.88ms | 105.37ms |

### After (event-driven via microtask)

| Scenario | Avg | P50 | P95 | P99 |
|----------|-----|-----|-----|-----|
| **Single dep (A&rarr;B)** | 21.9&micro;s | 12.5&micro;s | 48.7&micro;s | 121.6&micro;s |
| **Chain dep (4 levels)** | 30.4&micro;s | 28.2&micro;s | 47.9&micro;s | 64.3&micro;s |
| **Fan-out (1&rarr;5)** | 33.2&micro;s | 31.0&micro;s | 46.3&micro;s | 64.9&micro;s |

### Improvement

| Scenario | Before P50 | After P50 | Speedup |
|----------|-----------|----------|---------|
| **Single dep (A&rarr;B)** | 100.05ms | 0.012ms | **~8,000x** |
| **Chain (4 levels)** | 300.43ms | 0.028ms | **~10,700x** |
| **Fan-out (1&rarr;5)** | 100.11ms | 0.031ms | **~3,200x** |

<Aside type="tip">
Dependency chain latency dropped from **hundreds of milliseconds** to **microseconds**. This means multi-step pipelines (ETL, workflows, map-reduce) resolve nearly instantly instead of waiting for polling intervals.
</Aside>

```bash
# Run the dependency latency benchmark
bun run src/benchmark/dependency-latency.bench.ts
```

---

## Other Benchmarks

The repository includes additional specialized benchmarks:

| Benchmark | Purpose | File |
|-----------|---------|------|
| **Comprehensive** | Embedded vs TCP at scale | [`bench/comprehensive.ts`](https://github.com/egeominotti/bunqueue/blob/main/bench/comprehensive.ts) |
| **BullMQ Comparison** | bunqueue vs BullMQ (Redis) | [`bench/comparison/run.ts`](https://github.com/egeominotti/bunqueue/blob/main/bench/comparison/run.ts) |
| **Throughput** | Individual operation speeds | [`bench/throughput.bench.ts`](https://github.com/egeominotti/bunqueue/blob/main/bench/throughput.bench.ts) |
| **Worker** | Realistic worker simulation | [`bench/worker.bench.ts`](https://github.com/egeominotti/bunqueue/blob/main/bench/worker.bench.ts) |
| **Stress** | Production validation | [`bench/stress.bench.ts`](https://github.com/egeominotti/bunqueue/blob/main/bench/stress.bench.ts) |
| **Million Jobs** | High-volume integrity test | [`bench/million-jobs.bench.ts`](https://github.com/egeominotti/bunqueue/blob/main/bench/million-jobs.bench.ts) |
| **Dependency Latency** | Dependency chain resolution speed | [`src/benchmark/dependency-latency.bench.ts`](https://github.com/egeominotti/bunqueue/blob/main/src/benchmark/dependency-latency.bench.ts) |

```bash
# Run BullMQ comparison (requires Redis)
redis-server --daemonize yes
bun run start &
bun run bench/comparison/run.ts
```

---

## Submit Your Results

Run benchmarks on your hardware and share results via [GitHub Discussions](https://github.com/egeominotti/bunqueue/discussions).

Include:
- CPU model
- RAM
- Bun version
- OS
- Benchmark output
