DEV Community

Custodia-Admin
Custodia-Admin

Posted on

How PageBolt achieves 2-5 second screenshot latency (architecture deep dive)

How PageBolt achieves 2-5 second screenshot latency (architecture deep dive)

Latency kills. When your screenshot takes 30 seconds, your API times out. When your Vercel edge function runs Puppeteer, you hit the 10-second function timeout. Users bounce. Revenue dies.

PageBolt's screenshot endpoint responds in 2-5 seconds. Here's how.

The Problem: Why Local Chromium Is Slow

Running Chromium locally seems simple:

const browser = await puppeteer.launch();
Enter fullscreen mode Exit fullscreen mode

But this hides massive latency:

  1. Cold start: 3-8 seconds (launch Chromium, initialize V8, load browser context)
  2. Page load: 2-5 seconds (network, JavaScript execution, rendering)
  3. Screenshot capture: 0.5-1 second (DOM traversal, pixel rendering)
  4. Total: 5.5-14 seconds, and that's best case

On AWS Lambda or Vercel edge functions (10-second timeout), you fail silently. On a busy server, Chromium processes pile up and memory explodes.

The Solution: Distributed Browser Pool

PageBolt doesn't launch Chromium per request. Instead:

  1. Pre-warmed pools: Chromium instances run constantly in multiple regions (us-east, eu-west, ap-southeast)
  2. Connection pooling: Each instance handles 50-100 concurrent connections (not sequential requests)
  3. Intelligent routing: Requests route to the nearest region with available capacity
  4. Result caching: Screenshots of the same URL are cached for 24 hours

Result: New request comes in → Route to nearest pool → Reuse existing browser context → Screenshot → Cache → Return (2-5 seconds total)

Architecture Diagram

User Request
    ↓
Global Load Balancer (Route to nearest region)
    ↓
Regional Browser Pool
├─ Instance 1 (30 active connections)
├─ Instance 2 (25 active connections)
└─ Instance 3 (idle, ready)
    ↓
Screenshot Cache (Redis)
├─ URL hash → Image (24h TTL)
├─ Redirect if cached → Return (300ms)
└─ Miss → Render new → Cache → Return (3-5s)
Enter fullscreen mode Exit fullscreen mode

Performance Optimization Techniques

1. Pre-warmed Browser Contexts

Instead of launching fresh browsers, we maintain a pool of warm contexts:

// Cold start (Puppeteer)
const browser = await puppeteer.launch(); // 3-8s
const page = await browser.newPage(); // 1-2s
await page.goto(url); // 2-5s
// Total: 6-15s

// Warm pool (PageBolt)
const page = pool.getAvailablePage(); // 50-100ms (from pool)
await page.goto(url); // 2-3s (optimized)
// Total: 2.5-3.5s
Enter fullscreen mode Exit fullscreen mode

2. Aggressive Caching

Most screenshots are of the same URLs repeatedly. We cache aggressively:

const cacheKey = hash(url + options);
const cached = await redis.get(cacheKey);
if (cached) {
  return cached; // 300ms from Redis
}
// Cache miss → render → cache → return
Enter fullscreen mode Exit fullscreen mode

Cache hit rate: ~60-70% on production (huge latency win).

3. Network Optimization

Chromium's default network stack is slow. We optimize:

  • Block unnecessary resources: Ads, trackers, fonts (save 1-2s)
  • Parallel rendering: Execute JavaScript in parallel (save 0.5-1s)
  • Viewport scaling: Skip rendering off-screen content (save 0.3-0.5s)
await page.goto(url, {
  waitUntil: 'networkidle2', // Wait for network idle, not full load
  timeout: 8000 // Fail fast if page is slow
});
Enter fullscreen mode Exit fullscreen mode

Real-World Benchmarks

Scenario Puppeteer PageBolt Savings
Cold start 10-15s 2-3s 70-80%
Warm start (2nd req) 5-8s 2-3s 60-75%
Cached result N/A 0.3s Infinite
Vercel edge (cold) ❌ Timeout ✅ 3-4s Works
Lambda (concurrent) ❌ OOM ✅ 2-5s Works

Code Example: Measuring Latency

const start = Date.now();

const response = await fetch('https://pagebolt.dev/api/v1/screenshot', {
  method: 'POST',
  headers: {'x-api-key': YOUR_API_KEY},
  body: JSON.stringify({
    url: 'https://example.com',
    format: 'png'
  })
});

const latency = Date.now() - start;
console.log(`Screenshot took ${latency}ms`);
// Output: Screenshot took 2847ms (typical)
Enter fullscreen mode Exit fullscreen mode

Why This Matters

Serverless: Functions with 10-second timeouts now have room for:

  • 2-3s screenshot request
  • 2-3s additional processing
  • Safety margin

Scalability: Pre-warmed pools handle traffic spikes without cold starts.

Cost: One browser instance serving 50+ concurrent requests costs less than 50 on-demand instances.

Reliability: If one region is slow, traffic reroutes instantly.

Trade-offs

PageBolt's architecture sacrifices:

  • Custom browser setup (Puppeteer gives more control over browser flags)
  • Headful mode (screenshot-only, no interactive browser control)

But gains:

  • Massive latency reduction (2-5s vs 10-30s)
  • Instant scaling (no cold starts)
  • Production-ready (no memory leaks, no zombie processes)

Conclusion

PageBolt's 2-5 second latency comes from three pillars:

  1. Pre-warmed browser pools (no cold starts)
  2. Intelligent caching (60-70% hit rate saves 0.3s responses)
  3. Network optimization (block ads/trackers, parallel rendering)

Result: Screenshot APIs that scale, don't timeout, and cost less to run.


PageBolt is the fastest screenshot API. 2-5 second latency. Free tier: 100 requests/month.

Top comments (0)