āĻāĻ āϏāĻŋāϰāĻŋāĻāĻāĻž āϞā§āĻāĻžāϰ āĻāϏāϞ āĻāĻĻā§āĻĻā§āĻļā§āϝ debugging shortcuts āĻļā§āĻāĻžāύ⧠āύāĻžāĨ¤
āĻŦāϰāĻ āĻāĻŽāĻŋ āĻāĻžāĻ āĻāĻĒāύāĻžāϰāĻž āĻŦā§āĻā§āύ:
Systems āĻāϏāϞ⧠āĻā§āĻāĻžāĻŦā§ āĻā§āĻā§ āĻĒāĻĄāĻŧā§, āĻāĻŦāĻ āĻā§āύ āϤāĻžāϰāĻž āĻ āĻŋāĻ āĻāĻ āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āĻāĻĒāĻžāϝāĻŧā§āĻ āĻāĻžāĻāϤ⧠āĻŦāĻžāϧā§āϝ āĻšāϝāĻŧāĨ¤
āĻāĻŽāĻžāϰ āĻāĻāĻāĻž āĻŦāĻŋāĻļā§āĻŦāĻžāϏ āĻāĻā§ āĻāĻ āύāĻŋāϝāĻŧā§:
āĻā§āύ⧠system āĻšā§āĻ āĻāϰā§, random āĻāĻžāĻŦā§ fail āĻāϰ⧠āύāĻžāĨ¤
āĻĒā§āϰāϤāĻŋāĻāĻž failure āĻāϏāϞ⧠āϏā§āĻ system-āĻāϰ design-āĻāϰ āĻŽāϧā§āϝā§āĻ āϞā§āĻāĻž āĻĨāĻžāĻā§ â āĻļā§āϧ⧠āĻāĻŽāϰāĻž āϏā§āĻāĻž āĻāĻā§ āĻĨā§āĻā§ āĻĻā§āĻāĻŋ āύāĻžāĨ¤
āϤāĻžāĻ āĻāĻ āϏāĻŋāϰāĻŋāĻā§ āĻĒā§āϰāϤāĻŋāĻāĻž incident-āĻā§ āĻāĻŽāĻŋ āĻĻā§āĻāĻŦ āĻāĻ āĻĻā§āώā§āĻāĻŋāĻā§āĻŖ āĻĨā§āĻā§:
āĻāĻ āϏāĻŋāϰāĻŋāĻā§āϰ āĻĒā§āϰāϤāĻŋāĻāĻŋ āϏāĻŋāύāĻžāϰāĻŋāĻ āĻā§āύ⧠āĻāĻžāϞā§āĻĒāύāĻŋāĻ āĻĨāĻŋāĻāϰāĻŋ āĻŦāĻž āĻŦāĻ āĻĨā§āĻā§ āύā§āĻāϝāĻŧāĻž āύāϝāĻŧāĨ¤ āĻāĻā§āϞ⧠āĻāĻŽāĻžāϰ āύāĻŋāĻā§āϰ āĻā§āϝāĻžāϰāĻŋāϝāĻŧāĻžāϰ⧠āĻĢā§āϏ āĻāϰāĻž āĻŦāĻžāϏā§āϤāĻŦ āĻĒā§āϰā§āĻĄāĻžāĻāĻļāύ āĻā§āϰā§āϝāĻžāĻļ, āϰāĻžāϤā§āϰ āĻĒāϰ āϰāĻžāϤ āĻāĻžāĻāĻž āϏā§āĻā§āϰāĻžāĻāϞ āĻāĻŦāĻ āĻ āύ-āĻĢāĻŋāϞā§āĻĄ root cause āĻ ā§āϝāĻžāύāĻžāϞāĻŋāϏāĻŋāϏā§āϰ āĻ āĻāĻŋāĻā§āĻāϤāĻž āĻĨā§āĻā§ āϞā§āĻāĻžāĨ¤
| Field | Detail |
|---|---|
| Time | āϰāĻžāϤ ā§§ā§§:ā§Šā§¨ |
| Symptom | Dashboard load āĻšāĻā§āĻā§ āύāĻž, API hang āĻāϰāĻā§ |
| Root Cause | Disk 100% full â MySQL-āĻāϰ write path āĻĒā§āϰā§āĻĒā§āϰāĻŋ āĻŦā§āϞāĻ |
| Resolution Time | āĻĒā§āϰāĻžāϝāĻŧ ā§§ā§Ģ āĻŽāĻŋāύāĻŋāĻ |
| Severity | đ´ Critical |
âLahin bhai, system āĻ āύā§āĻ slowâĻ userāϰāĻž dashboard load āĻāϰāϤ⧠āĻĒāĻžāϰāĻā§ āύāĻžāĨ¤â
āĻāĻ āϧāϰāύā§āϰ message āĻĒā§āϞ⧠āĻĒā§āϰāĻĨāĻŽ instinct āĻšāϝāĻŧ āĻāĻžāĻŦāĻž āϝ⧠app āĻŦāĻž code-āĻ āĻā§āĻĨāĻžāĻ bug āĻāĻā§āĨ¤ āĻāĻŋāύā§āϤ⧠āĻŦā§āĻļāĻŋāϰāĻāĻžāĻ āϏāĻŽāϝāĻŧ āϏāĻŽāϏā§āϝāĻžāĻāĻž āĻ āύā§āĻ āύāĻŋāĻā§āϰ layer-āĻ āĻŦāϏ⧠āĻĨāĻžāĻā§āĨ¤
pm2 logs
API process āϤ⧠āĻŦā§āĻāĻā§ āĻāĻā§āĨ¤ Workers-āĻ āĻāϞāĻā§āĨ¤ āϏāĻŦ āĻĻā§āĻā§ āĻŽāύ⧠āĻšāĻā§āĻā§ āĻ āĻŋāĻāĻ āĻāĻā§āĨ¤
āϤāĻžāϰāĻĒāϰ āĻā§āĻ āĻāϰāĻž āĻšāϞā§:
curl /api/dashboard
â āĻāĻŋāĻā§āĻ āĻĢā§āϰāϤ āĻāϏāĻā§ āύāĻž, āĻļā§āϧ⧠hang āĻāϰ⧠āĻāĻā§āĨ¤
āĻāĻāĻžāĻ āĻāϏāϞ⧠āĻĒā§āϰāĻĨāĻŽ clue â process āĻā§āĻŦāĻŋāϤ, āĻāĻŋāύā§āϤ⧠āĻā§āύ⧠request-āĻ āĻāĻā§āĻā§āĻā§ āύāĻžāĨ¤ āĻŽāĻžāύ⧠āĻā§āĻĨāĻžāĻ āĻāĻāĻāĻž āĻāĻŋāύāĻŋāϏ āĻāĻāĻā§ āĻāĻā§āĨ¤
systemctl status mysql
â MySQL ârunningâ āĻĻā§āĻāĻžāĻā§āĻā§ â āĻāĻŋāύā§āϤ⧠āĻāĻ signal-āĻāĻž āĻāϏāϞ⧠āĻŦāĻŋāĻā§āϰāĻžāύā§āϤāĻŋāĻāϰāĨ¤
mysql -u root -p
â āĻāĻāĻžāĻ āĻāĻāĻā§ āĻā§āϞāĨ¤
āĻŽāĻžāύ⧠DB āĻā§āĻāύāĻŋāĻā§āϝāĻžāϞāĻŋ âupâ āĻāĻā§, āĻāĻŋāύā§āϤ⧠āĻāĻžāĻ āĻāϰāĻā§ āύāĻžāĨ¤ āĻĻā§āĻā§ āĻāϞāĻžāĻĻāĻž āĻāĻŋāύāĻŋāϏāĨ¤
df -h
â Disk 100% fullāĨ¤
āĻŦā§āϝāĻžāϏ, āĻāĻāĻžāύā§āĻ āĻĒā§āϰ⧠āĻāϞā§āĻĒā§āϰ āϰāĻšāϏā§āϝ āĻā§āϞ⧠āĻā§āϞāĨ¤
āĻāĻāĻž āĻā§āύ⧠crash āύāĻžāĨ¤
āĻāĻāĻž āĻšāϞ⧠backpressure āϝāĻžāϰ āĻā§āύ⧠escape path āύā§āĻ:
Request āĻāϏā§
â MySQL-āĻ write āĻāϰāϤ⧠āϝāĻžāϝāĻŧ
â Disk full, āϤāĻžāĻ āĻŦā§āϞāĻ āĻšāϝāĻŧā§ āϝāĻžāϝāĻŧ
â Transaction āĻāĻāĻā§ āĻĨāĻžāĻā§
â Connection āĻāĻāύ⧠release āĻšāϝāĻŧ āύāĻž
â Pool āĻāϰ⧠āϝāĻžāϝāĻŧ
â āĻĒā§āϰ⧠API layer āĻĨā§āĻŽā§ āϝāĻžāϝāĻŧ
System āĻāϏāϞ⧠fail āĻāϰāĻā§ āύāĻžāĨ¤ āϏ⧠āĻļā§āϧ⧠āϏā§āĻŽāĻžāύāĻžāϰ āϏāĻžāĻŽāύ⧠āĻĻāĻžāĻāĻĄāĻŧāĻŋāϝāĻŧā§ āĻ āύāύā§āϤāĻāĻžāϞ āĻ āĻĒā§āĻā§āώāĻž āĻāϰāĻā§āĨ¤
Disk Full
â Write path āĻŦā§āϞāĻ
â Transaction āĻļā§āώ āĻšāϤ⧠āĻĒāĻžāϰāĻā§ āύāĻž
â Connection āĻā§āϞāĻž āĻĨā§āĻā§ āϝāĻžāĻā§āĻā§
â Connection pool saturate
â āύāϤā§āύ āĻā§āύ⧠request āĻāĻā§āϤ⧠āĻĒāĻžāϰāĻā§ āύāĻž
â āϏāĻŋāϏā§āĻā§āĻŽ-āĻāϝāĻŧāĻžāĻāĻĄ stall
du -sh /* | sort -rh | head -20
āĻŦāĻŋāĻļā§āώāĻāĻžāĻŦā§ āĻā§āĻ āĻāϰāĻžāϰ āĻāĻžāϝāĻŧāĻāĻž:
āϤāĻžāϰāĻĒāϰ:
âāϏā§āϞ āĻļā§āϰ⧠āĻšāϤā§āĻ āĻĒā§āϰ⧠āĻ ā§āϝāĻžāĻĒ āĻĄāĻžāĻāύ!â
āĻĢā§āϞā§āϝāĻžāĻļ āϏā§āϞā§āϰ āĻĒā§āϰāĻĨāĻŽ āĻŽāĻŋāύāĻŋāĻā§āĻ āĻāĻ message â āĻāϰ āĻāĻ āϧāϰāύā§āϰ incident-āĻ āϏāĻŦāĻžāĻ āĻĒā§āϰāĻĨāĻŽā§ server āĻŦāĻž āĻāύāĻĢā§āϰāĻžāĻā§ āĻĻā§āώ āĻĻā§āϝāĻŧāĨ¤ āĻāϏāϞ āĻāĻžāϰāĻŖ āĻāĻŋāύā§āϤ⧠āĻ āύā§āϝ āĻāĻžāϝāĻŧāĻāĻžāϝāĻŧ āĻāĻŋāϞāĨ¤
100 users â 15,000 users
āĻšāĻ āĻžā§ āĻāϰā§āĻ āĻāĻ āĻāĻžāĻŽā§āĻĒāĨ¤ āĻā§āύ⧠warm-up āύā§āĻ, āϏāϰāĻžāϏāϰāĻŋ ā§§ā§Ģā§Ļx āĻā§āϰāĻžāĻĢāĻŋāĻāĨ¤
pm2 logs
Error āĻā§āϞā§:
āĻĒā§āϰāĻĨāĻŽ āĻĻā§āĻāĻžāϝāĻŧ āĻŽāύ⧠āĻšāϝāĻŧ âconnection āĻļāϰā§āĻā§āĻâ â āĻāĻŋāύā§āϤ⧠āĻāĻ āϧāĻžāϰāĻŖāĻžāĻāĻž āĻā§āϞ, āĻāĻŦāĻ āĻāĻāĻžāĻ āϏāĻŦāĻā§āϝāĻŧā§ āĻāĻŽāύ trapāĨ¤
SHOW STATUS LIKE 'Threads_running';
Threads_running = 10 (maxed out)
āĻāĻāĻž MySQL-āĻāϰ āĻā§āύ⧠hard limit āύāĻžāĨ¤ āĻāĻāĻž āĻāϏāϞ⧠application-āĻāϰ āύāĻŋāĻā§āϰ connection pool saturate āĻšāϝāĻŧā§ āĻāĻŋāϝāĻŧā§āĻāĻŋāϞāĨ¤
āĻāĻ āϏāĻŋāϏā§āĻā§āĻŽ connection-bound āύāĻžāĨ¤
āĻāĻāĻž time-boundāĨ¤
āĻāĻāĻāĻž slow query (~500ms)
â Connection āĻĻā§āϰā§āĻ āϏāĻŽāϝāĻŧ āϧāϰ⧠āϰāĻžāĻāĻž āĻšāϝāĻŧ
â Pool āϝāĻĨā§āώā§āĻ āϤāĻžāĻĄāĻŧāĻžāϤāĻžāĻĄāĻŧāĻŋ recycle āĻāϰāϤ⧠āĻĒāĻžāϰāĻā§ āύāĻž
â Queue āĻāĻŽāϤ⧠āĻļā§āϰ⧠āĻāϰā§
â Latency āĻāϰāĻ āĻŦāĻžāĻĄāĻŧā§
â āĻāĻŦāĻ āĻāĻāĻž āĻāĻāĻāĻž positive feedback loop-āĻ āĻĒāϰāĻŋāĻŖāϤ āĻšāϝāĻŧ
āĻŽāĻžāύ⧠āϏāĻŽāϏā§āϝāĻžāĻāĻž āύāĻŋāĻā§āĻ āύāĻŋāĻā§āĻā§ āĻāϰāĻ āĻāĻžāϰāĻžāĻĒ āĻāϰāĻāĻŋāϞāĨ¤
Missing Index
â Full table scan
â Query latency ~500ms
â DB connection āĻĻā§āϰā§āĻāϏāĻŽāϝāĻŧ āϧāϰ⧠āĻĨāĻžāĻāĻā§
â Connection pool saturate (10 threads)
â Request āĻāĻŽāĻž āĻšāĻā§āĻā§
â ETIMEDOUT + ER_CON_COUNT_ERROR
â āĻĒā§āϰ⧠āϏāĻŋāϏā§āĻā§āĻŽ āĻāϞāĻžāĻĒā§āϏ
10 threads / 0.5s = 20 QPS
āĻŽāĻžāύ⧠āϏāϰā§āĻŦā§āĻā§āĻ ā§¨ā§ĻāĻāĻž request āĻĒā§āϰāϤāĻŋ āϏā§āĻā§āύā§āĻĄā§ āĻšā§āϝāĻžāύā§āĻĄā§āϞ āĻāϰāĻžāϰ āĻā§āώāĻŽāϤāĻž āĻāĻŋāϞ â āĻāϰ āĻā§āϰāĻžāĻĢāĻŋāĻ āĻāĻŋāϞ āĻšāĻžāĻāĻžāϰ⧠āĻšāĻžāĻāĻžāϰāĨ¤
10 threads / 0.01s = 1000 QPS
āĻāĻāĻ ā§§ā§ĻāĻāĻž thread, āĻāĻŋāύā§āϤ⧠āĻāĻāύ ā§Ģā§Ļ āĻā§āĻŖ āĻŦā§āĻļāĻŋ throughputāĨ¤ Thread āĻŦāĻžāĻĄāĻŧāĻžāĻāύāĻŋ, āĻļā§āϧ⧠latency āĻāĻŽāĻŋāϝāĻŧā§āĻāĻŋāĨ¤
SHOW FULL PROCESSLIST;
CREATE INDEX idx_user_id;
āĻĢāϞāĻžāĻĢāϞ:
users table size: ~43 million rowsāύā§āĻ: āĻāĻ āĻāĻāύāĻžāĻāĻŋ MySQL 5.x-āĻ āĻāĻā§āĻāĻŋāϞ, āϝā§āĻāĻžāύā§
ALTER TABLE ... ADD COLUMN-āĻāϰ āĻŽāϤ⧠āĻ āύā§āĻ DDL āĻ āĻĒāĻžāϰā§āĻļāύ āĻā§āĻŦāĻŋāϞ āϰāĻŋāĻŦāĻŋāϞā§āĻĄ āĻāĻāĻžāϤ⧠āĻĒāĻžāϰāϤ āĻāĻŦāĻ āĻāϞā§āϞā§āĻāϝā§āĻā§āϝ āϏāĻŽāϝāĻŧ āϧāϰ⧠āĻŽā§āĻāĻžāĻĄā§āĻāĻž āϞāĻ āϧāϰ⧠āϰāĻžāĻāϤ⧠āĻĒāĻžāϰāϤāĨ¤ āĻāϧā§āύāĻŋāĻ MySQL 8 āĻāĻžāϰā§āϏāύāĻā§āϞ⧠āĻāĻ āϧāϰāύā§āϰ āĻ āύā§āĻ āĻ āĻĒāĻžāϰā§āĻļāύā§āϰ āĻāύā§āϝALGORITHM=INSTANTāϏāĻžāĻĒā§āϰā§āĻ āĻāϰā§, āϝāĻžāϰ āĻĢāϞ⧠āĻāĻ āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āϧāϰāύā§āϰ āĻŦā§āϝāϰā§āĻĨāϤāĻž āĻāĻāύ āĻ āύā§āĻ āĻāĻŽ āĻĻā§āĻāĻž āϝāĻžāϝāĻŧāĨ¤
| Field | Detail |
|---|---|
| Time | āĻĻā§āĻĒā§āϰ ⧍:ā§§ā§Ģ |
| Symptom | API suddenly hanging, database CPU low, connections increasing |
| Root Cause | A seemingly harmless migration acquired metadata locks and blocked the write path |
| Resolution | Kill migration session |
| Severity | đ´ Critical |
âāĻāĻžāĻ API āĻā§āĻŦ slow.â
āĻāϝāĻŧā§āĻ āĻŽāĻŋāύāĻŋāĻ āĻĒāϰā§:
âCreate user āĻāĻžāĻ āĻāϰāĻā§ āύāĻžāĨ¤â
āϤāĻžāϰāĻĒāϰ:
âCheckout āĻāĻžāĻ āĻāϰāĻā§ āύāĻžāĨ¤â
āϏāĻŦāĻā§āϝāĻŧā§ āĻ āĻĻā§āĻā§āϤ āĻŦāĻŋāώāϝāĻŧ āĻāĻŋāϞ:
āĻāĻŋāύā§āϤ⧠āĻĒā§āϰ⧠system āĻāĻžāϰā§āϝāϤ unusableāĨ¤
SHOW PROCESSLIST;
āĻĻā§āĻāĻž āĻā§āϞā§:
Waiting for table metadata lock
Waiting for table metadata lock
Waiting for table metadata lock
Waiting for table metadata lock
Deploy pipeline-āĻāϰ āĻ āĻāĻļ āĻšāĻŋāϏā§āĻŦā§ āĻāĻāĻāĻŋ migration run āĻšāϝāĻŧā§āĻāĻŋāϞ:
ALTER TABLE users
ADD COLUMN last_login_ip VARCHAR(45);
āĻĻā§āĻāϤ⧠harmlessāĨ¤
āĻāĻŋāύā§āϤ⧠users table-āĻ āĻāĻŋāϞ:
43 million rows
MySQL 5.x schema change āĻāϰāĻžāϰ āĻāĻā§ table-āĻāϰ āĻāĻĒāϰ metadata lock āύā§āϝāĻŧ āĻāĻŦāĻ āĻ āύā§āĻ DDL operation-āĻāϰ āĻā§āώā§āϤā§āϰ⧠table rebuild āĻāϰā§āĨ¤
āĻŽāĻžāĻāĻā§āϰā§āĻļāύ āĻļā§āϰ⧠āĻšāϞā§
â āĻŽā§āĻāĻžāĻĄā§āĻāĻž āϞāĻ āύā§āĻāϝāĻŧāĻž āĻšāϞā§
â āύāϤā§āύ write āĻ
āĻĒā§āĻā§āώāĻžāϝāĻŧ āĻĨāĻžāĻāϞ
â āĻā§āϰāĻžāύāĻā§āϝāĻžāĻāĻļāύ āĻāĻŽāĻž āĻšāϤ⧠āϞāĻžāĻāϞ
â āĻāĻžāύā§āĻāĻļāύ āĻĒā§āϞ āĻāϰ⧠āĻā§āϞ
â API āĻāĻāĻā§ āϝā§āϤ⧠āĻļā§āϰ⧠āĻāϰāϞ
â āϰāĻŋāĻā§āϰāĻžāĻ āĻŦāĻžāĻĄāĻŧāϤ⧠āϞāĻžāĻāϞ
â āĻĒā§āϰ⧠āϏāĻŋāϏā§āĻā§āĻŽ āĻĨāĻŽāĻā§ āĻā§āϞ
ALTER TABLE āĻļā§āϰ⧠āĻšāϞā§
â āĻŽā§āĻāĻžāĻĄā§āĻāĻž āϞāĻ āύā§āĻāϝāĻŧāĻž āĻšāϞā§
â INSERT/UPDATE āĻŦā§āϞāĻ āĻšāϝāĻŧā§ āĻā§āϞ
â āĻā§āϰāĻžāύāĻā§āϝāĻžāĻāĻļāύāĻā§āϞ⧠āĻā§āϞāĻž āĻĨā§āĻā§ āĻā§āϞ
â āĻāĻžāύā§āĻāĻļāύ āϰāĻŋāϞāĻŋāĻ āĻšāϞ⧠āύāĻž
â āĻĒā§āϞ saturation āĻĻā§āĻāĻž āĻĻāĻŋāϞ
â āϰāĻŋāĻā§āϝāĻŧā§āϏā§āĻ queue āĻŦāĻžāĻĄāĻŧāϤ⧠āĻĨāĻžāĻāϞ
â āϏāϰā§āĻŦāϤā§āϰ āĻāĻžāĻāĻŽāĻāĻāĻ
SHOW PROCESSLIST;
Output
Id User Command Time State
101 deploy Query 420 altering table
102 app Query 300 Waiting for table metadata lock
103 app Query 280 Waiting for table metadata lock
104 app Query 275 Waiting for table metadata lock
āĻāĻāĻžāύā§:
āϤāĻāύ:
KILL 101;
āĻĻāĻŋāϞā§:
gh-ost āĻŦāĻž pt-online-schema-change āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύ> āĻŦā§āĻļāĻŋāϰāĻāĻžāĻ āĻĒā§āϰā§āĻĄāĻžāĻāĻļāύ āĻāĻāĻā§āĻ āϏāĻŋāϏā§āĻā§āĻŽ āĻā§āĻā§ āĻĢā§āϞāĻžāϰ āĻāĻžāϰāĻŖā§ āĻšāϝāĻŧ āύāĻžāĨ¤
> āĻāĻā§āϞ⧠āĻšāϝāĻŧ āϤāĻāύ, āϝāĻāύ āϏāĻŋāϏā§āĻā§āĻŽāĻā§ āĻā§āϰāĻžāĻĢāĻŋāĻ āϏāĻžāϰā§āĻ āĻāϰāĻž āĻ
āĻŦāϏā§āĻĨāĻžāϤā§āĻ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰāϤ⧠āĻŦāϞāĻž āĻšāϝāĻŧāĨ¤
āĻāĻāĻž āĻā§āύ⧠bug fixing āĻāϞā§āĻĒ āύāĻžāĨ¤
āĻāĻāĻž āĻšāϞ⧠āĻāĻŽāύ āĻāĻāĻāĻž āĻāĻāύāĻž āϝā§āĻāĻžāύ⧠āϧāϰāĻž āĻšā§ā§āĻāĻŋāϞ:
âDatabase error āĻŽāĻžāύā§āĻ application handle āĻāϰ⧠āĻĢā§āϞāĻŦā§â
āĻāĻŋāύā§āϤ⧠production āϏā§āĻ āϧāĻžāϰāĻŖāĻž follow āĻāϰ⧠āύāĻžāĨ¤
Production āĻļā§āϧ⧠āϏā§āĻāĻžāĻ āĻāĻžāϞāĻžāϝāĻŧ āϝā§āĻāĻž āĻŦāĻžāϏā§āϤāĻŦā§ implement āĻāϰāĻž āĻšāϝāĻŧā§āĻā§āĨ¤
| Field | Detail |
|---|---|
| Time | āϰāĻžāϤ (approx) |
| Symptom | API flapping â restart loop, dashboard/API intermittently unreachable |
| Root Cause | Service layer-āĻ uncaught DB error â process crash â PM2 restart loop |
| Resolution | pm2 restart āĻĻāĻŋāϝāĻŧā§ stabilize, āĻĒāϰ⧠code-level fix |
| Severity | đ´ Critical |
Stack:
Controller Layer â try/catch āĻāĻŋāϞ
Service Layer â try/catch āĻāĻŋāϞ āύāĻž
POST /users
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50)
);
āĻāĻāĻāύ user āĻĒāĻžāĻ āĻžāϝāĻŧ:
name = "A very long string exceeding 50 characters........"
MySQL āĻ āĻŋāĻāĻāĻžāĻŦā§ reject āĻāϰā§:
ER_DATA_TOO_LONG: Data too long for column 'name'
(āĻāĻ error code-āĻāϰ āĻŽāĻžāύ⧠āĻšāϞ⧠â column-āĻ āϝāϤāĻā§āĻā§ capacity āĻāĻā§, āϤāĻžāϰ āĻā§āϝāĻŧā§ āĻŦā§āĻļāĻŋ data āĻĒāĻžāĻ āĻžāύ⧠āĻšāϝāĻŧā§āĻā§āĨ¤ MySQL āύāĻŋāĻā§āĻ āĻāĻŋāĻā§ āĻāĻžāĻā§āύāĻŋ, āϏ⧠āĻļā§āϧ⧠constraint enforce āĻāϰā§āĻā§āĨ¤)
āĻāĻāĻž expected behavior āĻāĻŋāϞāĨ¤
āĻāĻŋāύā§āϤ⧠āϏāĻŽāϏā§āϝāĻž āĻāĻāĻžāύ⧠āĻļā§āϰ⧠āĻšāϝāĻŧāĨ¤
pm2 list
ââââââŦâââââââââââŦââââââââââŦâââââââââŦââââââââââŦâââââââââââ
â id â name â status â âē â uptime â cpu â
ââââââŧâââââââââââŧââââââââââŧâââââââââŧââââââââââŧâââââââââââ¤
â 0 â api â online â 47 â 3s â 0% â
ââââââ´âââââââââââ´ââââââââââ´âââââââââ´ââââââââââ´âââââââââââ
đ âē (restart count) āĻ
āύā§āĻ āĻŦā§āĻļāĻŋ, uptime āĻŦāĻžāϰāĻŦāĻžāϰ āϰāĻŋāϏā§āĻ āĻšāĻā§āĻā§ â process āϏā§āĻĨāĻŋāϤāĻŋāĻļā§āϞ āĻšāĻā§āĻā§ āύāĻž, repeatedly crash āĻāϰāĻā§āĨ¤
pm2 logs api --lines 100
ER_DATA_TOO_LONG: Data too long for column 'name'
[PM2] App [api] exited with code 1
[PM2] App [api] starting in -fork mode-
[PM2] App [api] online
ER_DATA_TOO_LONG: Data too long for column 'name'
[PM2] App [api] exited with code 1
[PM2] App [api] starting in -fork mode-
[PM2] App [api] online
ER_DATA_TOO_LONG: Data too long for column 'name'
[PM2] App [api] exited with code 1
đ āĻāĻāĻ error āĻŦāĻžāϰāĻŦāĻžāϰ āĻĢāĻŋāϰ⧠āĻāϏāĻā§ â pattern repeat āĻāϰāĻā§, random crash āύāĻžāĨ¤
Controller layer-āĻ try/catch āĻāĻŋāϞ:
// controller.js
async function createUser(req, res) {
try {
const user = await userService.create(req.body.name);
return res.status(201).json(user);
} catch (err) {
return res.status(500).json({ error: "Something went wrong" });
}
}
āĻāĻŋāύā§āϤ⧠service layer-āĻ āĻā§āύ⧠try/catch āĻāĻŋāϞ āύāĻž:
// userService.js
async function create(name) {
// No try/catch here â query error throws straight up
const result = await db.query(
`INSERT INTO users (name) VALUES (?)`,
[name]
);
return result;
}
āĻĻā§āĻāϤ⧠āĻŽāύ⧠āĻšāϝāĻŧ controller-āĻāϰ try/catch āĻĒā§āϰ⧠request lifecycle āĻā§ cover āĻāϰāĻŦā§ â service layer āϝā§āĻāĻžāύā§āĻ error throw āĻāϰā§āĻ, āϏā§āĻāĻž await chain āϧāϰ⧠controller-āĻāϰ catch āĻĒāϰā§āϝāύā§āϤ bubble up āĻāϰāĻž āĻāĻāĻŋāϤāĨ¤
āĻāĻŋāύā§āϤ⧠practically, āĻāĻāĻžāύ⧠error escape āĻāϰā§āĻāĻŋāϞ â āĻāĻžāϰāĻŖ error properly await āĻāϰāĻž āĻšāϝāĻŧāύāĻŋ āĻā§āύ⧠āĻāĻāĻāĻž āĻāĻžāϝāĻŧāĻāĻžāϝāĻŧ (āĻāĻāĻāĻž fire-and-forget call, āĻŦāĻž āĻāĻāĻāĻž non-awaited promise āĻāϰ āĻā§āϤāϰ⧠error āĻĨā§āϰ⧠āĻšāϝāĻŧā§āĻāĻŋāϞ), āϝāĻžāϰ āĻĢāϞ⧠āϏā§āĻāĻž controller-āĻāϰ synchronous catch boundary-āϰ āĻŦāĻžāĻāϰ⧠āĻāĻŋāϝāĻŧā§ unhandled rejection āĻšāĻŋāϏā§āĻŦā§ process-āĻā§ crash āĻāϰāĻŋāϝāĻŧā§āĻā§āĨ¤
đ Lesson: âāĻāĻāĻāĻž try/catch āĻĨāĻžāĻāϞā§āĻ āϝāĻĨā§āώā§āĻâ āĻāĻ āϧāĻžāϰāĻŖāĻžāĻāĻžāĻ āĻā§āϞ āĻāĻŋāϞāĨ¤ Error āϝā§āĻāĻžāύ⧠actually throw āĻšāϝāĻŧ, catch āϏā§āĻāĻžāύā§āĻ āĻĨāĻžāĻāϤ⧠āĻšāϝāĻŧ â āĻāĻĒāϰā§āϰ layer-āĻāϰ catch āύāĻŋāĻā§āϰ layer-āĻāϰ āĻĒā§āϰāϤāĻŋāĻāĻž throw path āĻā§ guarantee āĻāϰ⧠āύāĻž, āĻŦāĻŋāĻļā§āώ āĻāϰ⧠async/promise chain āĻ āĻŋāĻāĻāĻžāĻŦā§ āύāĻž āĻĨāĻžāĻāϞā§āĨ¤
āĻĢāϞāĻžāĻĢāϞ:
process.exit() call āĻāĻžāĻĄāĻŧāĻžāĻ)đ āĻāĻŦāĻ process terminate āĻšāϝāĻŧā§ āϝāĻžāϝāĻŧ, PM2 restart āĻāϰā§, āĻāĻŋāύā§āϤ⧠āĻĒāϰā§āϰ request āĻāϏāϞ⧠āĻāĻŦāĻžāϰ āĻāĻāĻ āĻāĻžāϝāĻŧāĻāĻžāϝāĻŧ crash āĻāϰā§āĨ¤
Service layer-āĻ error throw
â
Controller-āĻāϰ catch escape āĻāϰā§
â
Node process crash (unhandled rejection)
â
PM2 detects crash â restart
â
āĻĒāϰā§āϰ identical request āĻ āĻāĻŦāĻžāϰ same crash
â
Restart count āĻŦāĻžāĻĄāĻŧāϤ⧠āĻĨāĻžāĻā§ (47+)
System unstable, from outside āĻĻā§āĻāϤ⧠āĻŽāύ⧠āĻšāĻā§āĻāĻŋāϞ:
âAPI randomly down / flappingâ
pm2 restart api
đ āĻāĻ āĻāĻŽāĻžāύā§āĻĄ āĻāĻžāϞāĻžāύā§āϰ āĻĒāϰ system stable āĻšāϝāĻŧā§ āĻāĻŋāϝāĻŧā§āĻāĻŋāϞ â loop āĻĨā§āĻŽā§ āĻāĻŋāϝāĻŧā§āĻāĻŋāϞāĨ¤
āĻāĻāĻž āĻāĻāĻāĻž āĻā§āϰā§āϤā§āĻŦāĻĒā§āϰā§āĻŖ āĻĒāϝāĻŧā§āύā§āĻ: āĻāĻ incident āĻāĻāĻāĻž self-sustaining infinite loop āĻāĻŋāϞ āύāĻžāĨ¤ āĻāĻāĻž āĻāĻŋāϞ āĻāĻāĻ bad input āĻŦāĻžāϰāĻŦāĻžāϰ āĻāϏāĻžāϰ āĻĢāϞ⧠āϤā§āϰāĻŋ āĻšāĻāϝāĻŧāĻž āĻāĻāĻāĻž crash burst â manual restart āĻĻā§āĻāϝāĻŧāĻžāϰ āϏāĻŽāϝāĻŧ āĻĨā§āĻā§ āύāϤā§āύ āĻā§āύ⧠invalid request āύāĻž āĻāϏāĻžāϝāĻŧ system āϏā§āϏā§āĻĨ āĻ āĻŦāϏā§āĻĨāĻžāϝāĻŧ āĻĨā§āĻā§ āĻāĻŋāϝāĻŧā§āĻāĻŋāϞāĨ¤ Restart āύāĻŋāĻā§ āĻāĻŋāϝāĻŧā§ underlying bug āĻā§ fix āĻāϰā§āύāĻŋ â āĻļā§āϧ⧠āϏāĻžāĻŽāϝāĻŧāĻŋāĻāĻāĻžāĻŦā§ crash chain āĻāĻž āĻā§āĻā§ āĻĻāĻŋāϝāĻŧā§āĻāĻŋāϞāĨ¤ āϏā§āĻ bad input āĻāĻŦāĻžāϰ āĻāϏāϞ⧠crash āĻāĻŦāĻžāϰ āĻšāϤā§, āϝāϤāĻā§āώāĻŖ āύāĻž code-level fix āĻĻā§āĻāϝāĻŧāĻž āĻšāϝāĻŧāĨ¤
MySQL āĻāĻāĻžāύ⧠āĻā§āύ⧠āϏāĻŽāϏā§āϝāĻž āĻāϰā§āύāĻŋ â āϏ⧠āĻļā§āϧ⧠āĻŦāϞā§āĻā§ data column capacity exceed āĻāϰāĻā§āĨ¤
Real issue āĻāĻŋāϞ architectural:
Controller layer-āĻāϰ error handling-āĻā§ âāĻĒā§āϰ⧠request lifecycle-āĻāϰ safety netâ āĻāĻžāĻŦāĻž āĻšāϝāĻŧā§āĻāĻŋāϞ, āĻāĻŋāύā§āϤ⧠service layer-āĻāϰ āĻā§āϤāϰā§āϰ āĻāĻāĻāĻž uncaught throw path āϏā§āĻ boundary-āĻā§ bypass āĻāϰ⧠āĻāĻŋāϝāĻŧā§āĻāĻŋāϞāĨ¤
āϤāĻŋāύāĻāĻž component individually āϤāĻžāĻĻā§āϰ āύāĻŋāĻā§āϰ āĻāĻžāϝāĻŧāĻāĻžāϝāĻŧ āĻ āĻŋāĻ āĻāĻžāĻ āĻāϰā§āĻā§:
â Correct constraint enforcement
â try/catch āĻāĻŋāϞ, āĻāĻŋāύā§āϤ⧠āϏā§āĻāĻžāϰ coverage āĻāĻŋāϞ incomplete â āϏāĻŦ throw path cover āĻāϰā§āύāĻŋ
â āĻā§āύ⧠try/catch āĻāĻŋāϞ āύāĻž â error āϏāϰāĻžāϏāϰāĻŋ uncaught āĻĨā§āĻā§ process crash āĻāϰāĻŋāϝāĻŧā§āĻā§
â Crash detect āĻāϰ⧠restart āĻāϰā§āĻā§ (expected behavior) â āĻāĻŋāύā§āϤ⧠pm2 restart manual intervention-āĻ āĻāϏāϞ⧠loop āĻĨāĻžāĻŽāĻŋāϝāĻŧā§āĻā§, PM2-āϰ auto-restart āύāĻŋāĻā§ āĻĨā§āĻā§ āĻāĻŋāĻā§ âāĻ āĻŋāĻâ āĻāϰā§āύāĻŋ
āĻāĻāĻāĻž upper-layer try/catch āĻĨāĻžāĻāĻž āĻŽāĻžāύā§āĻ âerror handledâ â āĻāĻ assumption āĻāĻžāĻ false security āĻĻāĻŋāϝāĻŧā§āĻāĻŋāϞāĨ¤
Single bad request āĻāĻāĻāĻž crash trigger āĻāϰāϞ⧠â PM2 restart āĻāϰāϞ⧠â āĻāĻŦāĻžāϰ same/similar bad request āĻāϞ⧠āĻāĻŦāĻžāϰ crash â āĻāĻ pattern āϰāĻŋāĻĒāĻŋāĻ āĻšāϝāĻŧā§ restart count āĻŦāĻžāĻĄāĻŧāϤ⧠āĻĨāĻžāĻāϞ⧠â āϝāϤāĻā§āώāĻŖ manual restart āύāĻž āĻĻā§āĻāϝāĻŧāĻž āĻšāϞ⧠āĻāĻŦāĻ traffic pattern āĻŦāĻĻāϞāĻžāϞā§āĨ¤
āĻā§āϞ āϧāĻžāϰāĻŖāĻž āĻāĻŋāϞ:
âController-āĻ try/catch āĻāĻā§, āϤāĻžāĻ āĻĒā§āϰ⧠request safeāĨ¤â
Reality:
āĻĒā§āϰāϤāĻŋāĻāĻž layer-āĻāϰ own error boundary āĻĒā§āϰāϝāĻŧā§āĻāύāĨ¤ Upper layer-āĻāϰ catch āύāĻŋāĻā§āϰ layer-āĻāϰ āĻĒā§āϰāϤāĻŋāĻāĻž throw/reject path āĻā§ automatically cover āĻāϰ⧠āύāĻž â āĻŦāĻŋāĻļā§āώ āĻāϰ⧠async code-āĻ, āϝā§āĻāĻžāύ⧠āĻāĻāĻāĻž missed
awaitāĻŦāĻž un-awaited promise āϏāĻšāĻā§āĻ catch boundary āĻŦāĻžāĻāĻĒāĻžāϏ āĻāϰāϤ⧠āĻĒāĻžāϰā§āĨ¤
// userService.js
async function create(name) {
try {
return await db.query(
`INSERT INTO users (name) VALUES (?)`,
[name]
);
} catch (err) {
if (err.code === "ER_DATA_TOO_LONG") {
const validationError = new Error("Input too long");
validationError.statusCode = 400;
throw validationError;
}
throw err;
}
}
đ āĻĒā§āϰāϤāĻŋāĻāĻž layer āύāĻŋāĻā§āϰ errors āύāĻŋāĻā§ handle āĻāϰ⧠āĻāĻŦāĻ proper, predictable error shape upward pass āĻāϰ⧠â controller-āĻāϰ catch āϤāĻāύ āĻāĻāĻāĻž known shape-āĻāϰ āĻāĻĒāϰ āĻāĻžāĻ āĻāϰāϤ⧠āĻĒāĻžāϰā§āĨ¤
if (name.length > 50) {
return res.status(400).json({
error: "Name exceeds maximum allowed length"
});
}
// ecosystem.config.js
module.exports = {
apps: [{
name: "api",
script: "./server.js",
max_restarts: 15, // hard ceiling instead of unlimited
min_uptime: "10s", // crash within 10s doesn't count as a "successful" run
exp_backoff_restart_delay: 100 // exponential backoff between restarts
}]
};
đ āĻāĻ configuration āĻĨāĻžāĻāϞ⧠repeated crash-āĻāϰ āĻā§āώā§āϤā§āϰ⧠PM2 āύāĻŋāĻā§āĻ restart āĻŦāύā§āϧ āĻāϰ⧠process-āĻā§ errored state-āĻ āϰāĻžāĻāϤ⧠â manual intervention āĻāϰ āĻāύā§āϝ āĻ
āĻĒā§āĻā§āώāĻž āύāĻž āĻāϰāĻŋāϝāĻŧā§ āĻāĻāĻāĻž clean, alertable failure āϤā§āϰāĻŋ āĻšāϤā§āĨ¤
process.exit() āĻŦā§āϝāĻŦāĻšāĻžāϰā§āϰ āύā§āϤāĻŋprocess.exit() āĻļā§āϧ⧠āĻāĻ āĻā§āώā§āϤā§āϰ⧠use āĻāϰāĻž āĻāĻāĻŋāϤ:
â āĻāĻāύā§āĻ user input errors-āĻāϰ āĻāύā§āϝ āύāϝāĻŧ â āĻāĻŦāĻ āĻāĻ incident-āĻ āĻā§āύ⧠explicit process.exit() call āĻāĻŋāϞāĻ āύāĻž; crash āĻšāϝāĻŧā§āĻāĻŋāϞ Node-āĻāϰ default unhandled-rejection behavior āĻĨā§āĻā§āĨ¤
Systems donât fail randomly â they fail exactly according to their design boundaries.
āĻāĻ case āĻ boundary āĻāĻž āĻāĻŋāϞ layer-āĻāĻŋāϤā§āϤāĻŋāĻ, error-path āĻāĻŋāϤā§āϤāĻŋāĻ āύāĻž:
āĻĒā§āϰāϤāĻŋāĻĻāĻŋāύ āϰāĻžāϤ ⧧⧍āĻāĻžāϝāĻŧ (Asia/Dhaka, UTC+6) āĻāĻāĻāĻž āĻĄā§āĻāϞāĻŋ āϰāĻŋāĻĒā§āϰā§āĻ/āĻŦāĻŋāϞāĻŋāĻ āĻāĻŦ(CRON) āϰāĻžāύ āĻšāĻāϝāĻŧāĻžāϰ āĻāĻĨāĻž āĻāĻŋāϞāĨ¤ āĻāĻŋāύā§āϤ⧠āĻāĻāĻāĻžāϰāϰāĻž āϰāĻŋāĻĒā§āϰā§āĻ āĻāϰāϞ⧠āϝ⧠āϰāĻŋāĻĒā§āϰā§āĻ āĻāĻāύ⧠ā§Ŧ āĻāĻŖā§āĻāĻž āĻāĻā§, āĻāĻāύ⧠ā§Ŧ āĻāĻŖā§āĻāĻž āĻĒāϰ⧠āĻāϏāĻā§ â āĻāĻāύ⧠āĻāĻāύ⧠āĻĒā§āϰā§āĻĒā§āϰāĻŋ āĻŽāĻŋāϏāĻŋāĻ, āĻāĻŦāĻžāϰ āĻāĻāύ⧠āĻāĻāĻ āĻĻāĻŋāύ⧠āĻĻā§āĻāĻŦāĻžāϰ āϰāĻžāύ āĻšāϝāĻŧā§ āϝāĻžāĻā§āĻā§āĨ¤
CRON āĻāύā§āĻā§āϰāĻŋ āĻĻā§āĻāϤ⧠āϏāĻ āĻŋāĻāĻ āĻŽāύ⧠āĻšāĻā§āĻāĻŋāϞā§: 0 0 * * *
āϞāĻ āĻā§āĻ āĻāϰ⧠āĻĻā§āĻāĻž āĻā§āϞā§, āĻāĻŦ āĻ āĻŋāĻāĻ āĻĢāĻžāϝāĻŧāĻžāϰ āĻšāĻā§āĻā§ â āĻāĻŋāύā§āϤ⧠āĻāĻā§āϰ āĻĻāĻŋāύ āϏāύā§āϧā§āϝāĻž ā§ŦāĻāĻžāϝāĻŧ, āύāĻžāĻšāϞ⧠āϏāĻāĻžāϞ ā§ŦāĻāĻžāϝāĻŧāĨ¤
āϏāĻžāϰā§āĻāĻžāϰ⧠date āĻāĻŽāĻžāύā§āĻĄ āĻĻāĻŋāϝāĻŧā§ āĻĻā§āĻāĻž āĻā§āϞ⧠āϏāĻžāϰā§āĻāĻžāϰ UTC āĻāĻžāĻāĻŽā§ āĻāϞāĻā§, āϞā§āĻāĻžāϞ āĻāĻžāĻāĻŽā§ āύāĻž â āĻāĻŋāύā§āϤ⧠āϝ⧠āĻĄā§āĻā§āϞāĻĒāĻžāϰ CRON āĻāĻā§āϏāĻĒā§āϰā§āĻļāύāĻāĻž āϞāĻŋāĻā§āĻāĻŋāϞā§, āϏ⧠āĻŽāĻžāĻĨāĻžāϝāĻŧ āĻĸāĻžāĻāĻžāϰ āĻāĻžāĻāĻŽ āϰā§āĻā§ 0 0 * * * āϞāĻŋāĻā§āĻāĻŋāϞā§āĨ¤
āĻāϰā§āĻāĻā§ āĻāĻā§āϰ⧠āĻāĻŋāϝāĻŧā§ āĻĻā§āĻāĻž āĻā§āϞā§: āϏāĻŋāϏā§āĻā§āĻŽ CRON OS-āĻāϰ āĻāĻžāĻāĻŽāĻā§āύ āĻ āύā§āϝāĻžāϝāĻŧā§ āĻāϞ⧠(āĻā§āϞāĻžāĻāĻĄ āĻāύāϏā§āĻā§āϝāĻžāύā§āϏ⧠āϏāĻžāϧāĻžāϰāĻŖāϤ āĻĄāĻŋāĻĢāϞā§āĻ UTC āĻĨāĻžāĻā§), āĻ āĻĨāĻ āĻ ā§āϝāĻžāĻĒā§āϞāĻŋāĻā§āĻļāύ āύāĻŋāĻā§ TZ āĻāύāĻāĻžāϝāĻŧāϰāύāĻŽā§āύā§āĻ āĻā§āϝāĻžāϰāĻŋāϝāĻŧā§āĻŦāϞ āĻŦāĻž āĻā§āύ⧠āĻĄā§āĻ āϞāĻžāĻāĻŦā§āϰā§āϰāĻŋāϰ āĻŽāĻžāϧā§āϝāĻŽā§ Asia/Dhaka āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻāĻŋāϞ⧠â āĻŽāĻžāύ⧠āĻāĻāĻ āϞāĻāĻŋāĻā§āϝāĻžāϞ āĻāĻŦā§āϰ āĻāύā§āϝ āĻĻā§āĻāĻāĻž āĻāϞāĻžāĻĻāĻž āĻāĻĄāĻŧāĻŋ āĻāĻžāĻ āĻāϰāĻāĻŋāϞā§āĨ¤
āĻŦā§āύāĻžāϏ āϏāĻŽāϏā§āϝāĻž: āĻĒāϰ⧠āϝāĻĻāĻŋ āĻ ā§āϝāĻžāĻĒā§āϞāĻŋāĻā§āĻļāύāĻāĻž āĻŽāĻžāϞā§āĻāĻŋ-āϰāĻŋāĻāĻŋāϝāĻŧāύ/āĻāύā§āĻā§āĻāύāĻžāϰ⧠āĻĄāĻŋāĻĒā§āϞāϝāĻŧ āĻāϰāĻž āĻšāϝāĻŧ, āĻĒā§āϰāϤāĻŋāĻāĻž āĻāύā§āĻā§āĻāύāĻžāϰā§āϰ TZ āϏā§āĻāĻŋāĻ āĻāϞāĻžāĻĻāĻž āĻšāϤ⧠āĻĒāĻžāϰ⧠â āϤāĻāύ âāĻāĻāĻâ CRON āĻāϞāĻžāĻĻāĻž āĻāϞāĻžāĻĻāĻž āĻŽā§āĻļāĻŋāύ⧠āĻāϞāĻžāĻĻāĻž āĻāϞāĻžāĻĻāĻž āϰāĻŋāϝāĻŧā§āϞ-āĻāϝāĻŧāĻžāϰā§āϞā§āĻĄ āϏāĻŽāϝāĻŧā§ āĻĢāĻžāϝāĻŧāĻžāϰ āĻšāĻŦā§āĨ¤
āĻĒā§āϰāĻĨāĻŽā§ āĻŽāύ⧠āĻšāϝāĻŧā§āĻāĻŋāϞ āϏāĻŽāϏā§āϝāĻžāĻāĻž billing calculation logic-āĻāĻ āĻāĻā§ â āĻšāϝāĻŧāϤ⧠usage aggregation query āĻā§āϞ date range āϧāϰāĻā§āĨ¤ āĻāĻŋāĻŽ āĻĒā§āϰāĻĨāĻŽ āĻāĻŋāĻā§ āϏāĻŽāϝāĻŧ query-āĻ āϰāĻŋāĻāĻŋāĻ āĻāϰāϞā§āĨ¤
āĻāĻŋāύā§āϤ⧠āĻāϏāϞ āϏāĻŽāϏā§āϝāĻžāĻāĻž query-āϤ⧠āĻāĻŋāϞā§āĻ āύāĻžāĨ¤ āĻĄā§āĻā§āϞāĻĒāĻžāϰ āύāĻŋāĻā§āϰ āĻŽāĻžāĻĨāĻžāϰ āĻāĻžāĻāĻŽāĻā§āύ āϧāϰ⧠cron āĻāĻā§āϏāĻĒā§āϰā§āĻļāύ āϞāĻŋāĻāϞ⧠â āϏāĻŋāϏā§āĻā§āĻŽ cron āϏā§āĻāĻžāĻā§ OS/āĻāύā§āĻā§āĻāύāĻžāϰā§āϰ āĻāĻžāĻāĻŽāĻā§āύ⧠āĻāύā§āĻāĻžāϰāĻĒā§āϰā§āĻ āĻāϰāϞ⧠(āϏāĻžāϧāĻžāϰāĻŖāϤ UTC) â āĻŽāĻŋāϏāĻŽā§āϝāĻžāĻ â āĻāĻŦ āĻā§āϞ āϏāĻŽāϝāĻŧā§ āĻĢāĻžāϝāĻŧāĻžāϰ āĻšāϞ⧠â āĻāϰ āĻĄāĻžāĻāύāϏā§āĻā§āϰāĻŋāĻŽ āĻĒā§āϰāĻāĻžāĻŦ (āĻĄāĻžāĻŦāϞ-āĻāĻžāϰā§āĻāĻŋāĻ, āĻŽāĻŋāϏāĻŋāĻ āĻĄā§āĻāϞāĻŋ āϰāĻŋāĻĒā§āϰā§āĻ, āĻ āύā§āϝ āĻāĻŦā§āϰ āϏāĻžāĻĨā§ āĻ āϰā§āĻĄāĻžāϰ āύāĻŋāϝāĻŧā§ āϰā§āϏ āĻāύā§āĻĄāĻŋāĻļāύ)āĨ¤
# āĻĄā§āĻā§āϞāĻĒāĻžāϰ āϝāĻž āĻā§āĻŦā§āĻāĻŋāϞā§āύ:
0 0 * * * â "āϰāĻžāϤ ⧧⧍āĻāĻž, āĻŽāĻžāύ⧠Dhaka midnight"
# cron daemon āϝāĻž āĻāϏāϞ⧠āĻāϰāϞā§:
0 0 * * * â "00:00 UTC" = "06:00 AM Dhaka time" (ā§Ŧ āĻāĻŖā§āĻāĻž āĻĒāĻžāϰā§āĻĨāĻā§āϝ)
node-cron āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠explicitly timezone āĻ
āĻĒāĻļāύ āĻĒāĻžāϏ āĻāϰ⧠āĻĻā§āĻāϝāĻŧāĻž āĻšāϞ⧠â āĻāϤ⧠āϏāĻžāϰā§āĻāĻžāϰā§āϰ OS timezone āϝāĻžāĻ āĻšā§āĻ āύāĻž āĻā§āύ, job āϏāĻŦāϏāĻŽāϝāĻŧ āϏāĻ āĻŋāĻ āϞā§āĻāĻžāϞ āϏāĻŽāϝāĻŧā§ āĻĢāĻžāϝāĻŧāĻžāϰ āĻšāĻŦā§:const cron = require("node-cron");
cron.schedule(
"0 0 * * *",
() => runDailyBilling(),
{ timezone: "Asia/Dhaka" }
);
timedatectl set-timezone UTC
Cron āĻā§āύ⧠āĻāĻžāĻāĻŽāĻā§āύ āĻŦā§āĻā§ āύāĻž â āĻļā§āϧ⧠āĻŽā§āĻļāĻŋāύā§āϰ system clock āĻ āύā§āϏāϰāĻŖ āĻāϰā§āĨ¤
āĻā§āϞāĻžāĻāĻĄ āĻāύāϏā§āĻā§āϝāĻžāύā§āϏ/āĻāύā§āĻā§āĻāύāĻžāϰ āĻĒā§āϰāĻžāϝāĻŧ āϏāĻŦāϏāĻŽāϝāĻŧ āĻĄāĻŋāĻĢāϞā§āĻ UTC â āϏāĻžāϰā§āĻāĻžāϰā§āϰ āϞā§āĻāĻžāϞ āĻāĻžāĻāĻŽ āĻāĻĒāύāĻžāϰ āϞā§āĻāĻžāϞ āĻāĻžāĻāĻŽā§āϰ āϏāĻžāĻĨā§ āĻŽāĻŋāϞāĻŦā§ āĻāĻāĻž āϧāϰ⧠āύā§āĻāϝāĻŧāĻž āϝāĻžāĻŦā§ āύāĻžāĨ¤
āĻā§āύ⧠āĻāĻŦā§āϰ āĻ āϰā§āĻĨ āϝāĻĻāĻŋ āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āĻāĻžāĻāĻŽāĻā§āύā§āϰ āϏāĻžāĻĨā§ āĻŦāĻžāĻāϧāĻž āĻĨāĻžāĻā§, āϏā§āĻ āĻ āϰā§āĻĨāĻāĻžāĻā§ UTC-āϤ⧠āĻāύāĻāĻžāϰā§āĻ āĻāϰ⧠cron expression-āĻ āϞāĻŋāĻā§āύ, āĻāϰ āĻāĻŽā§āύā§āĻā§ āĻŦā§āϝāĻžāĻā§āϝāĻž āϰāĻžāĻā§āύāĨ¤
DST āĻŽā§āύ⧠āĻāϞāĻž āĻāĻžāĻāĻŽāĻā§āύā§āĻ āϏāϤāϰā§āĻ āĻĨāĻžāĻāϤ⧠āĻšāĻŦā§ (āĻŦāĻžāĻāϞāĻžāĻĻā§āĻļ āĻĒā§āϰāϝā§āĻā§āϝ āύāĻž, āϤāĻŦā§ āĻāύā§āϤāϰā§āĻāĻžāϤāĻŋāĻ āϏāĻŋāϏā§āĻā§āĻŽā§ āĻā§āϰā§āϤā§āĻŦāĻĒā§āϰā§āĻŖ)āĨ¤
| Field | Detail |
|---|---|
| Time | Deploy-āĻāϰ āĻĒāϰā§āϰ āĻĻāĻŋāύ, āϏāĻāĻžāϞ |
| Symptom | /dashboard-āĻ refresh āĻĻāĻŋāϞā§āĻ 404, āĻāĻŋāύā§āϤ⧠āϏāϰāĻžāϏāϰāĻŋ homepage āĻĨā§āĻā§ navigate āĻāϰāϞ⧠āĻ āĻŋāĻāĻ āĻžāĻ āĻāĻžāĻ āĻāϰ⧠|
| Root Cause | Nginx file-system-āĻāĻŋāϤā§āϤāĻŋāĻ routing āĻāĻļāĻž āĻāϰāĻāĻŋāϞ, āĻāĻŋāύā§āϤ⧠SPA route āĻā§āϞ⧠client-side JavaScript-āĻ resolve āĻšāĻā§āĻāĻŋāϞ â āϏāĻžāϰā§āĻāĻžāϰ⧠āϏā§āĻ path-āĻāϰ āĻā§āύ⧠āĻĢāĻžāĻāϞ āύā§āĻ |
| Resolution | try_files directive āĻĻāĻŋāϝāĻŧā§ āϏāĻŦ unknown route-āĻā§ index.html-āĻ fallback āĻāϰāĻžāύ⧠|
| Severity | đ High (user-facing, āĻāĻŋāύā§āϤ⧠data loss āύā§āĻ) |
âāĻāĻžāĻ, dashboard page refresh āĻĻāĻŋāϞā§āĻ 404 āĻĻā§āĻāĻžāĻā§āĻā§āĨ¤ āĻāĻŋāύā§āϤ⧠āϞāĻŋāĻāĻā§ āĻā§āϞāĻŋāĻ āĻāϰāϞ⧠āĻ āĻŋāĻāĻ āĻāĻžāĻ āĻāϰā§!â
āĻāĻ āϧāϰāύā§āϰ bug report āĻļā§āύāϞ⧠āĻĒā§āϰāĻĨāĻŽā§ āĻŽāύ⧠āĻšāϝāĻŧ frontend routing-āĻ āĻā§āύ⧠bug āĻāĻā§āĨ¤ āĻāĻŋāύā§āϤ⧠āĻāϏāϞ āϏāĻŽāϏā§āϝāĻž client āĻāĻŦāĻ server â āĻĻā§āĻ āĻāĻžāϝāĻŧāĻāĻžāϝāĻŧ route āĻŦā§āĻāĻžāϰ āĻĻā§āĻāĻāĻž āϏāĻŽā§āĻĒā§āϰā§āĻŖ āĻāϞāĻžāĻĻāĻž āĻŽāĻĄā§āϞā§āϰ āĻŽāϧā§āϝā§āĨ¤
example.com â click "Dashboard" link â example.com/dashboard āϞā§āĻĄ āĻšāϝāĻŧ
āĻā§āύ⧠problem āύā§āĻāĨ¤ URL āĻŦāĻĻāϞā§āĻā§, page-āĻ āĻŦāĻĻāϞā§āĻā§āĨ¤
example.com/dashboard â press F5 (refresh)
â 404 Not Found
đ āĻāĻāĻ URL, āĻāĻŋāύā§āϤ⧠āĻāĻāĻŦāĻžāϰ āĻāĻžāĻ āĻāϰāĻā§, āĻāĻāĻŦāĻžāϰ āĻāϰāĻā§ āύāĻžāĨ¤ āĻŽāĻžāύ⧠āϏāĻŽāϏā§āϝāĻžāĻāĻž route āύāĻŋāĻā§ āύāϝāĻŧ â āϏāĻŽāϏā§āϝāĻž āĻšāϞ⧠āĻā§āĻāĻžāĻŦā§ āĻāĻ route-āĻ āĻĒā§āĻāĻāĻžāύ⧠āĻšāĻā§āĻā§āĨ¤
āĻā§āϞāĻŋāĻ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ:
No network request sent for /dashboard
Refresh āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ:
GET /dashboard â 404
đ āĻāĻāĻžāύā§āĻ clue āĻĒāĻžāĻāϝāĻŧāĻž āĻā§āϞ â link click-āĻāϰ āϏāĻŽāϝāĻŧ āĻā§āύ⧠HTTP request-āĻ Nginx āĻĒāϰā§āϝāύā§āϤ āϝāĻžāĻā§āĻā§ āύāĻžāĨ¤ āĻĒā§āϰā§āĻāĻžāĻ browser-āĻāϰ āĻā§āϤāϰ⧠handle āĻšāĻā§āĻā§āĨ¤
cat /etc/nginx/sites-available/default
location / {
try_files $uri $uri/ =404;
}
đ āĻĒāĻžāĻāϝāĻŧāĻž āĻā§āϞ āĻāϏāϞ āĻāĻžāϰāĻŖ â =404 āĻŽāĻžāύ⧠Nginx-āĻā§ āĻŦāϞāĻž āĻāĻā§, file āĻŦāĻž directory āύāĻž āĻĒāĻžāĻāϝāĻŧāĻž āĻā§āϞ⧠āϏāϰāĻžāϏāϰāĻŋ 404 āĻĢā§āϰāϤ āĻĻāĻŋāϤā§āĨ¤ Nginx-āĻāϰ āĻāĻžāĻā§ /dashboard āĻŽāĻžāύ⧠disk-āĻ āĻĨāĻžāĻāĻž āĻāĻāĻāĻž āĻĢāĻžāĻāϞ āĻŦāĻž āĻĢā§āϞā§āĻĄāĻžāϰ â āϝāĻž āĻāĻĻāϤ⧠āĻāĻāύ⧠āĻŦāĻžāύāĻžāύā§āĻ āĻšāϝāĻŧāύāĻŋāĨ¤
āĻāĻāĻž āĻā§āύ⧠crash āĻŦāĻž bug āύāĻž â āĻāĻāĻž āĻĻā§āĻ layer-āĻāϰ routing model-āĻāϰ āĻŽāϧā§āϝ⧠āĻāĻāĻāĻž mismatchāĨ¤
Browser āĻāĻāĻāĻž link-āĻ click āĻāϰā§
â React Router URL āĻŦāĻĻāϞ⧠āĻĻā§āϝāĻŧ (pushState)
â āĻā§āύ⧠server request āϝāĻžāϝāĻŧāĻ āύāĻž
â Component client-side render āĻšāϝāĻŧ
â āϏāĻŦ āĻ āĻŋāĻāĻ āĻžāĻ āĻĻā§āĻāĻžāϝāĻŧ
āĻāĻŋāύā§āϤ⧠refresh āĻāϰāϞā§:
â Browser āĻāĻāĻĻāĻŽ fresh GET request āĻĒāĻžāĻ āĻžāϝāĻŧ
â Nginx āϏā§āĻ path-āĻā§ āĻĢāĻžāĻāϞ-āϏāĻŋāϏā§āĻā§āĻŽ path āĻšāĻŋāϏā§āĻŦā§ treat āĻāϰā§
â /dashboard āύāĻžāĻŽā§ āĻā§āύ⧠āĻĢāĻžāĻāϞ āĻŦāĻž folder āύā§āĻ
â Nginx 404 āĻĢā§āϰāϤ āĻĻā§āϝāĻŧ â JavaScript āϞā§āĻĄ āĻšāĻāϝāĻŧāĻžāϰ āϏā§āϝā§āĻāĻ āĻĒāĻžāϝāĻŧ āύāĻž
Nginx āĻā§āϞ āĻāĻŋāĻā§ āĻāϰā§āύāĻŋ â āϏ⧠āύāĻŋāĻā§āϰ āύāĻŋāϝāĻŧāĻŽ āĻ āύā§āϝāĻžāϝāĻŧā§ āĻ āĻŋāĻāĻ āĻāĻžāĻ āĻāϰāĻā§āĨ¤ āϏāĻŽāϏā§āϝāĻž āĻšāϞā§, SPA routing model-āĻāϰ āϏāĻžāĻĨā§ āĻāĻ āύāĻŋāϝāĻŧāĻŽāĻāĻž āĻāĻāύ⧠align āĻāϰāĻžāύā§āĻ āĻšāϝāĻŧāύāĻŋāĨ¤
SPA deploy āĻāϰāĻž āĻšāϝāĻŧ (client-side routing āϏāĻš)
â Nginx config-āĻ āĻļā§āϧ⧠literal file/folder lookup āĻāĻā§
â Client navigation request āĻĒāĻžāĻ āĻžāϝāĻŧ āύāĻž (JS intercept āĻāϰā§)
â Refresh/direct-URL hit āϏāϰāĻžāϏāϰāĻŋ Nginx-āĻā§ āĻāϏāϞ path āĻāĻŋāĻā§āĻā§āϏ āĻāϰā§
â āĻĄāĻŋāϏā§āĻā§ āϏā§āĻ path-āĻāϰ āĻā§āύ⧠file āύā§āĻ
â try_files $uri $uri/ =404 fallback āĻā§āϰāĻŋāĻāĻžāϰ āĻšāϝāĻŧ
â Nginx 404 āĻĒāĻžāĻ āĻžāϝāĻŧ, index.html āĻāĻāύ⧠āϞā§āĻĄ āĻšāϝāĻŧ āύāĻž
â React Router-āĻāϰ āϏā§āϝā§āĻāĻ āĻĨāĻžāĻā§ āύāĻž route resolve āĻāϰāĻžāϰ
server {
listen 80;
server_name example.com;
root /var/www/my-spa-app;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
sudo nginx -t
sudo systemctl reload nginx
try_files āϧāĻžāĻĒā§ āϧāĻžāĻĒā§ āϝāĻž āĻāϰā§$uri â exact file āĻāĻā§ āĻāĻŋāύāĻž āĻā§āĻ āĻāϰ⧠(āϝā§āĻŽāύ logo.png)āĨ¤ āĻĨāĻžāĻāϞ⧠āϏāϰāĻžāϏāϰāĻŋ serve āĻāϰā§āĨ¤$uri/ â file āύāĻž āĻšāϞ⧠directory āĻāĻŋāύāĻž āĻā§āĻ āĻāϰā§āĨ¤/index.html â āĻā§āύā§āĻāĻžāĻ āύāĻž āĻĨāĻžāĻāϞ⧠(āϝā§āĻŽāύ /dashboard), index.html āĻĢā§āϰāϤ āĻĻā§āϝāĻŧāĨ¤ Browser SPA āϞā§āĻĄ āĻāϰā§, client-side router URL āĻĻā§āĻā§ āĻ āĻŋāĻ component āĻŦāĻžāύāĻžāϝāĻŧāĨ¤āĻĢāϞāĻžāĻĢāϞ: refresh āĻāϰāϞā§āĻ āĻāϰ 404 āĻāϏ⧠āύāĻž, āĻāĻžāϰāĻŖ Nginx āĻāĻāύ routing decision client-side JavaScript-āĻāϰ āĻšāĻžāϤ⧠āĻā§āĻĄāĻŧā§ āĻĻā§āϝāĻŧ, āύāĻŋāĻā§ judge āĻāϰāĻžāϰ āĻā§āώā§āĻāĻž āĻāϰ⧠āύāĻžāĨ¤
âāϝāĻĻāĻŋ āĻā§āϞāĻŋāĻ āĻāϰ⧠āĻāĻžāĻ āĻāϰā§, āϤāĻžāĻšāϞ⧠route-āĻāĻž āĻ āĻŋāĻ āĻāĻā§â â āĻāĻ assumption-āĻāĻžāĻ āĻŦāĻŋāĻā§āϰāĻžāύā§āϤāĻŋāĻāϰāĨ¤
Client-side navigation āĻāϰ server-side request â āĻāĻ āĻĻā§āĻā§ āϏāĻŽā§āĻĒā§āϰā§āĻŖ āĻāϞāĻžāĻĻāĻž pathāĨ¤ QA-āϤ⧠āϝāĻĻāĻŋ āĻā§āĻ āĻļā§āϧ⧠click āĻāϰ⧠test āĻāϰā§, refresh āĻāĻāύ⧠āύāĻž āĻāϰā§, āĻāĻ bug āĻĒā§āϰā§āĻĄāĻžāĻāĻļāύ⧠āϝāĻžāĻāϝāĻŧāĻž āĻĒāϰā§āϝāύā§āϤ āϧāϰāĻžāĻ āĻĒāĻĄāĻŧāĻŦā§ āύāĻžāĨ¤ āĻāϰ deep-link āĻļā§āϝāĻŧāĻžāϰ āĻāϰāĻž (āĻāĻžāĻāĻā§ āϏāϰāĻžāϏāϰāĻŋ /dashboard āϞāĻŋāĻāĻ āĻĒāĻžāĻ āĻžāύā§) āĻāĻāĻ āĻāĻžāϰāĻŖā§ āĻā§āĻā§ āϝāĻžāĻŦā§ â āĻāĻžāϰāĻŖ āϏā§āĻāĻžāĻ āĻāĻāĻāĻž fresh server requestāĨ¤
## 𧨠Common Gotchas (Fix āĻāϰāĻžāϰ āĻĒāϰā§āĻ āϝāĻž āĻŽāĻžāĻĨāĻžāϝāĻŧ āϰāĻžāĻāϤ⧠āĻšāĻŦā§)
### 1. Real 404 āĻšāĻžāϰāĻŋāϝāĻŧā§ āϝāĻžāϝāĻŧ
example.com/this-route-does-not-exist-anywhere ```
āĻāĻāύ āĻāĻāĻžāĻ index.html-āĻ fallback āĻšāϝāĻŧā§ āϝāĻžāĻŦā§ â Nginx-level 404 āĻāϰ āĻĻā§āĻāĻž āϝāĻžāĻŦā§ āύāĻžāĨ¤ āĻāϰ āĻŽāĻžāύ⧠router āύāĻŋāĻā§āĻ āĻāĻāĻāĻž catch-all âNot Foundâ route define āĻāϰāϤ⧠āĻšāĻŦā§, āύāĻžāĻšāϞ⧠user āĻāĻāĻāĻž broken page-āĻā§ valid page āĻā§āĻŦā§ āĻŦāϏ⧠āĻĨāĻžāĻāĻŦā§āĨ¤
index.html Cachingindex.html āϝāĻĻāĻŋ aggressively cache āĻšāϝāĻŧ, āύāϤā§āύ deploy āĻāϰāĻžāϰ āĻĒāϰā§āĻ user āĻĒā§āϰāύ⧠JS bundle reference āĻāϰāĻž version āĻĻā§āĻāϤ⧠āĻĨāĻžāĻāĻŦā§āĨ¤ index.html-āĻāϰ āĻāύā§āϝ Cache-Control: no-cache āϰāĻžāĻāĻž āĻāĻžāϞā§, āĻāϰ static asset (JS/CSS bundle)-āĻāϰ āĻāύā§āϝ hashed filename + long-term cachingāĨ¤
Server āĻāĻāύ⧠āĻāĻžāύ⧠āύāĻž client-side router-āĻāϰ āĻā§āϤāϰ⧠āĻā§ āĻā§ route define āĻāϰāĻž āĻāĻā§ â āϤāĻžāĻ āϤāĻžāĻā§ āĻŦāϞ⧠āĻĻāĻŋāϤ⧠āĻšāϝāĻŧ, âāϤā§āĻŽāĻžāϰ āϝāĻž āĻā§āύāĻžāϰ āĻāĻĨāĻž āύāĻž, āϏā§āĻāĻžāϰ fallback āĻĻāĻŋāϝāĻŧā§ āĻĻāĻŋāĻāĨ¤â