Skip to content

50ms Hot Reload: The Fastest Development Experience

How Gati achieves sub-100ms hot reload for instant feedback.

The Problem

Traditional frameworks:

  • Express: 2-5 seconds (full restart)
  • NestJS: 3-8 seconds (full rebuild)
  • Next.js: 1-3 seconds (HMR)

Gati: 50-200ms (incremental)

How It Works

1. Incremental Analysis

typescript
// Only analyze changed file
const changes = detectChanges(file);
if (changes.length === 0) return; // Skip

// Analyze only affected handlers
for (const handler of affectedHandlers) {
  reanalyze(handler);
}

2. Module Hot Swap

typescript
// Swap module without restart
const newModule = await import(`${file}?t=${Date.now()}`);
moduleRegistry.replace(moduleName, newModule);

3. Route Re-registration

typescript
// Update routes in-place
router.unregister(oldRoute);
router.register(newRoute, newHandler);

4. Zero Downtime

Request 1 → Old Handler (completes)

Hot Reload (50ms)

Request 2 → New Handler (uses updated code)

Benchmarks

FrameworkHot ReloadFull Restart
ExpressN/A2-5s
NestJSN/A3-8s
Next.js1-3s5-10s
Gati50-200ms1-2s

Developer Experience

Before (Express)

bash
# Edit file
vim src/routes/users.js

# Restart server (3s)
npm restart

# Test change
curl http://localhost:3000/users

# Total: ~5 seconds per change

After (Gati)

bash
# Edit file
vim src/handlers/users/[id].ts

# Auto-reload (50ms)
# ✅ Already done

# Test change
curl http://localhost:3000/users/123

# Total: ~1 second per change

5x faster iteration

What Gets Reloaded

Instant (50-200ms)

  • Handler code
  • Module exports
  • Route definitions
  • Middleware

⚠️ Fast (500ms-1s)

  • Configuration changes
  • Module dependencies
  • Type definitions

Requires restart

  • Port changes
  • Environment variables
  • Global state

Real-World Impact

Scenario: Bug Fix

Traditional:

  1. Edit code (30s)
  2. Restart server (3s)
  3. Test (10s)
  4. Repeat 5x = 215 seconds

Gati:

  1. Edit code (30s)
  2. Auto-reload (0.05s)
  3. Test (10s)
  4. Repeat 5x = 200 seconds

Saved: 15 seconds per iteration

Scenario: Feature Development

Traditional: 10 iterations × 5s = 50 seconds waiting

Gati: 10 iterations × 0.05s = 0.5 seconds waiting

Saved: 49.5 seconds = 99% faster

Technical Details

File Watching

typescript
const watcher = chokidar.watch('src/**/*.ts', {
  ignoreInitial: true,
  awaitWriteFinish: {
    stabilityThreshold: 100,
    pollInterval: 50
  }
});

watcher.on('change', async (file) => {
  const start = Date.now();
  await hotReload(file);
  console.log(`Reloaded in ${Date.now() - start}ms`);
});

Module Cache Busting

typescript
// Clear require cache
delete require.cache[require.resolve(file)];

// Import with timestamp
const module = await import(`${file}?t=${Date.now()}`);

Configuration

typescript
// gati.config.ts
export default {
  dev: {
    hotReload: {
      enabled: true,
      debounce: 100, // ms
      verbose: true
    }
  }
};

Released under the MIT License.