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
| Framework | Hot Reload | Full Restart |
|---|---|---|
| Express | N/A | 2-5s |
| NestJS | N/A | 3-8s |
| Next.js | 1-3s | 5-10s |
| Gati | 50-200ms | 1-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 changeAfter (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 change5x 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:
- Edit code (30s)
- Restart server (3s)
- Test (10s)
- Repeat 5x = 215 seconds
Gati:
- Edit code (30s)
- Auto-reload (0.05s)
- Test (10s)
- 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
}
}
};