#engineering
70 bài viết về chủ đề này
Zero-downtime Migration — đổi schema khi app đang chạy
Đổi schema trên DB đang chạy production mà không downtime: expand-contract, ADD COLUMN an toàn, index CONCURRENTLY và backfill theo batch.
pprof trong Go — tìm thủ phạm ngốn CPU và RAM
Chạy pprof đúng cách để tìm hot path CPU, memory leak và goroutine kẹt trong service Go — kèm code mẫu và mấy cái bẫy em từng dính.
Nén payload API — gzip, Brotli hay zstd cho backend?
Bật gzip chưa chắc đã nhanh. So sánh gzip, Brotli, zstd, cái bẫy Vary header, middleware nén trong Go và 3 cạm bẫy hay gặp.
Mutation Testing — Coverage 90% mà bug vẫn lọt lưới
Coverage 90% chưa chắc test tốt. Mutation testing tự sửa code để xem test có bắt được bug thật không, kèm ví dụ Go với gremlins.
OOMKilled — Pod bị kill dù RAM còn thừa
Pod bị OOMKilled dù node còn dư RAM? Hiểu request vs limit, cgroup v2, GOMEMLIMIT và cách debug exit code 137 trong Kubernetes.
Message Queue: Nạp task vào hàng đợi, worker xử lý nền mau lẹ
Đừng làm việc nặng ngay trong request HTTP. Bài này nói cách đẩy task vào hàng đợi, worker xử lý nền kèm retry + dead-letter queue bằng Go.
Redis làm khóa phân tán — đừng tưởng SETNX xong là xong
SETNX tưởng đủ để làm distributed lock nhưng giấu cả đống bẫy: key hết hạn, unlock nhầm, gặp critical section lâu. Đây là cách làm cho đúng.
Distributed Tracing — rượt tìm lỗi chậm trong hệ thống microservice
OpenTelemetry giúp xâu chuỗi request qua nhiều service để tìm đúng nút thắt cổ chai thay vì đoán mò.
Transaction Isolation — 4 mức cô lập trong PostgreSQL, chọn sao cho đúng?
Hiểu 3 mức cô lập giao dịch trong PostgreSQL: Read Committed, Repeatable Read, Serializable — chọn đúng để khỏi ghi sai dữ liệu.
Goroutine Leak trong Go — Leak chỗ nào, chữa bằng gì
Goroutine rẻ nhưng không miễn phí. Bài này chỉ chỗ Goroutine leak thường gặp và cách bắt bằng runtime.NumGoroutine + pprof.
Outbox Pattern — Ghi DB rồi publish event, không lo mất
Outbox Pattern giải bài toán dual-write: ghi DB vừa publish event vừa an toàn, không mất mát. Có code Go và relay thực chiến.
Cache-Aside: Vì sao bọc Redis ngoài DB vẫn có thể chậm
Cache-aside tưởng đơn giản mà dính Cache Stampede, thiếu TTL jitter, ghi nhầm thứ tự. 3 cái bẫy làm chậm hệ thống dù đã bọc Redis.
GitHub Actions — Pipeline CI/CD tự động cho dự án thật sự
CI/CD bằng GitHub Actions từ A đến Z: workflow syntax, cache dependency, matrix build, secrets và deployment tự động lên production an toàn.
Connection Pool — Vì sao mở kết nối DB mỗi lần là chậm ngất?
Vì sao mở kết nối PostgreSQL mỗi lần request là chậm? Học cách tinh chỉnh connection pool trong Go: MaxOpenConns, MaxIdleConns, ConnMaxLifetime và các cái bẫy dễ dính.
Flaky Tests — Khi test chạy được lúc thì không, chữa cách nào?
Flaky test âm thầm giết chết niềm tin vào CI. Tìm hiểu 4 nguyên nhân chính và cách sửa dứt điểm để test chạy 100 lần vẫn xanh.
Idempotency Keys — Chống ghi trùng khi API retry an toàn
Hướng dẫn dùng Idempotency-Key + unique constraint để API retry an toàn, không ghi trùng order hay thanh toán 2 lần — kèm code Go + PostgreSQL.
CAP Theorem — Vì sao hệ thống phân tán luôn phải chọn 2 trong 3?
CAP là gì, vì sao không thể có đủ Consistency, Availability, Partition tolerance cùng lúc, và cách chọn combo đúng cho hệ thống thực tế.
Graceful Shutdown trong Go — Tắt app không rớt một request nào
Graceful shutdown trong Go: bắt SIGTERM, dừng nhận request mới, chờ request dở xong rồi mới tắt. Code mẫu + kinh nghiệm thực tế.
CQRS — Tách đọc khỏi ghi, app scale ngon hơn hẳn
CQRS tách command với query, mỗi chiều một model riêng. Xem cách triển khai thực tế + khi nào nên (và không nên) dùng.
PostgreSQL Partitioning — Chia bảng to, query nhanh như chớp
Học table partitioning trong PostgreSQL: chia bảng to đã tăng tốc query, dọn data cũ nhanh gọn, kèm code thực chiến.
Load Balancing: Từ Round Robin đến Consistent Hashing
Tìm hiểu các thuật toán load balancing từ Round Robin đến Consistent Hashing — lợi hại của từng loại và khi nào nên xài cho hệ thống thật.
Composite Index trong PostgreSQL — Vì sao index chồng index vẫn chậm?
Composite index giúp query tăng tốc gấp 10 lần, nhưng đặt sai thứ tự cột là vô dụng. Hiểu quy tắc Leftmost Prefix và covering index trong PostgreSQL.
Terraform cho người mới — Quản lý hạ tầng bằng code từ số 0
Infrastructure as Code với Terraform: state, plan/apply, module. Kèm ví dụ code và kinh nghiệm thực tế để quản lý hạ tầng như code.
Contract Testing — Chặn 2 team sửa API phá nhau
Contract testing giúp chặn 2 team cùng sửa API phá nhau. Tìm hiểu Pact, provider/consumer và cách triển khai thực tế.
Backpressure — Khi producer nhanh hơn consumer thì sao?
Backpressure giúp hệ thống không sụp khi producer nhanh hơn consumer: drop, block, backoff hay adaptive. Kèm code Go thực chiến.
Cache-Aside với Redis — Giảm tải database cực kỳ đơn giản
Tìm hiểu pattern Cache-Aside với Redis: cách đọc/ghi cache đúng chuẩn, tránh cache stampede, kèm code ví dụ và kinh nghiệm triển khai thực tế.
Event-driven Architecture — Bỏ gọi API, nói chuyện qua sự kiện
Event-driven architecture giúp hệ thống decouple và scale mượt mà. Học event, event bus, outbox pattern cùng kinh nghiệm thực chiến.
Fan-in Fan-out trong Go — Chia việc cho goroutine, gom kết quả lại
Fan-in fan-out giúp xử lý hàng ngàn tác vụ song song bằng goroutine rồi gom kết quả — kèm code mẫu Go và kinh nghiệm thực chiến.
EXPLAIN ANALYZE — Vũ khí săn query chậm trong database
Tối ưu SQL query bằng EXPLAIN ANALYZE: đọc execution plan, tìm sequential scan, thêm index đúng chỗ, biến query 3 giây thành 30ms.
Connection pooling — Tại sao app chậm dù database khỏe re?
Connection pooling tái sử dụng kết nối database, giảm latency và tránh lỗi 'too many connections'. Kinh nghiệm config pool đúng cách trong Go.
Zero-downtime deployment — Blue-Green và Canary thực chiến
Blue-Green và Canary release giúp deploy không downtime, rollback nhanh. Kèm ví dụ nginx + docker-compose và kinh nghiệm thực tế.
Property-based testing — Để máy tự sinh input tìm bug giùm mình
Property-based testing thay vì đoán input, máy tự sinh hàng trăm ngàn case để tìm bug — kèm ví dụ Go thực chiến.
Idempotency key — Chống trừ tiền 2 lần khi API bị retry
Idempotency key giúp API xử lý an toàn khi client retry: trùng request vẫn trả kết quả cũ, không bao giờ trừ tiền 2 lần.
Go pprof thực chiến — Tìm bottleneck và rò rỉ memory
Profile CPU, heap và goroutine bằng pprof trong Go: cách bật endpoint, đọc flame graph và kinh nghiệm bắt bottleneck thực tế.
Hexagonal Architecture — Kiến trúc đặt domain làm trung tâm
Hiểu Hexagonal Architecture (Ports & Adapters) qua ví dụ Go: tách business logic khỏi framework và database, code dễ test và dễ thay đổi hơn hẳn.
Đổi schema database không downtime — Expand & Contract thực chiến
Migrate schema Postgres an toàn trên production: expand & contract, backfill theo batch, chuyển code từng phase — không cần tắt service.
TypeScript Generics thực chiến — Viết code tổng quát mà vẫn an toàn
Generics trong TypeScript qua ví dụ thực tế: generic function, extends, keyof, infer và cách tránh over-engineering khi áp dụng vào dự án.
Thundering Herd — Khi cache hết hạn là cả hệ thống sụp
Thundering herd là gì? Khi một key cache 'nóng' hết hạn, hàng chục nghìn request cùng đổ vào database. Kèm cách chặn: singleflight, Redis lock và jitter TTL.
Docker multi-stage build — Cắt image từ 1.2GB xuống 90MB
Học multi-stage build trong Docker để giảm image từ 1.2GB xuống 90MB — kèm Dockerfile mẫu, tricks layer cache và kinh nghiệm deploy VPS thực tế.
Testcontainers — Hết cảnh mock database khi viết integration test
Testcontainers chạy PostgreSQL, Redis thật trong Docker cho integration test — hết cảnh mock giả, test sát production hơn. Kèm ví dụ Go.
Pragmatic Programmer – Topic 47: Working Together — Code chung
Topic 47 Pragmatic Programmer: pair programming và mob programming — vì sao code chung lại cho kết quả tốt hơn, và làm sao để pair thật sự hiệu quả.
Goroutine Leak trong Go — Kẻ giết RAM thầm lặng
Goroutine leak âm thầm ăn hết RAM của bạn. Nhận diện 3 pattern leak kinh điển và fix bằng context + select + goleak.
Pragmatic Programmer – Topic 46: Solving Impossible Puzzles — Phá bẫy
Topic 46 Pragmatic Programmer: bài toán 'bất khả thi' thường chỉ bị giới hạn bởi suy nghĩ của chính mình. Cách nhận diện ràng buộc tự đặt và phá bẫy.
Kafka, RabbitMQ hay Redis Streams? Chọn message queue cho backend
So sánh Kafka, RabbitMQ và Redis Streams: ưu nhược điểm, khi nào dùng cái nào, kèm code Go consumer với retry và dead letter queue.
Pragmatic Programmer – Topic 45: The Requirements Pit — Đào bới yêu cầu
Yêu cầu hiếm khi nằm trên bề mặt — Topic 45: đào bới yêu cầu thật, biến requirements thành hội thoại, dùng project glossary.
API Gateway — Cánh cửa duy nhất của backend hiện đại
API Gateway là cửa ngõ duy nhất cho mọi request: routing, auth tập trung, aggregation. Kèm code Go thực chiến và khi nào KHÔNG nên dùng.
PostgreSQL Indexing thực chiến — B-tree, GIN và cái bẫy hay gặp
Index là con dao hai lưỡi: đúng thì query chạy như gió, sai thì database phình to. Học B-tree, GIN, partial index và cách tránh bẫy thực tế.
Pragmatic Programmer – Topic 44: Naming Things — Đặt Tên Cho Đúng
Cái tên quyết định code dễ đọc hay ác mộng. Topic 44 Pragmatic Programmer — đặt tên theo ý định, không theo cách thực hiện.
Observability cho Backend — OTel, Metrics & Tracing thực chiến
Log chỉ kể chuyện gì xảy ra, metrics & tracing mới trả lời vì sao. Setup OpenTelemetry trong Go: tracer, span, histogram — kèm bài học thực tế.
Integration Testing với Testcontainers — Test thật, không mock
Học cách dùng Testcontainers để viết integration test với dependency thật (Postgres, Redis) trong Go — không mock, chạy CI mượt, code an tâm hơn.
Pragmatic Programmer – Topic 43: Stay Safe Out There — Bảo Vệ Code Trước Thế Giới Bên Ngoài
Topic 43 — Stay Safe Out There: bảo vệ code của bạn khỏi thế giới bên ngoài với nguyên tắc validate input, least privilege, defense in depth, và encryption.
Pragmatic Programmer – Topic 42: Property-Based Testing — Để Framework Tự Tìm Bug Cho Bạn
Property-based testing giúp phát hiện edge case mà example-based test không bao giờ thấy — trải nghiệm với fast-check, Hypothesis và QuickCheck.
Graceful Shutdown trong Go — Signal, Context & bài học thực tế
Học cách graceful shutdown HTTP server, worker pool và background jobs trong Go bằng signal.Notify, context và sync.WaitGroup từ kinh nghiệm production thực tế.
Test to Code — Nếu Không Test, Thì Code Của Bạn Không Hoạt Động (Pragmatic Programmer #41)
Testing không phải là giai đoạn riêng — nó là một phần của coding. Cảm nhận về Topic 41 từ Pragmatic Programmer.
Redis Caching — Cache Aside, Read Through và chiến lược cho production
Tìm hiểu chiến lược cache với Redis: Cache Aside, Read Through, Write Through kèm code Go thực tế và kinh nghiệm production.
Pragmatic Programmer – Topic 40: Refactoring — Dám đụng vào code cũ
Refactoring trong Pragmatic Programmer — cách tiếp cận code cũ như khu vườn cần chăm sóc, không phải toà nhà chỉ xây một lần
Docker Multi-Stage Builds — Từ 1.2GB xuống 15MB
Học cách dùng multi-stage build trong Docker để giảm kích thước image Go app từ 1.2GB xuống chỉ 15MB — nhanh hơn, an toàn hơn khi deploy.
Error Handling trong Rust — Result, Option và câu chuyện `?`
Rust không có exception, chỉ có Result và Option. Mình chia sẻ cách xử lý lỗi trong Rust — từ unwrap tới error chains với anyhow và thiserror.
PostgreSQL EXPLAIN ANALYZE & Composite Index — Cặp bài trùm query chậm
Học cách đọc EXPLAIN ANALYZE và thiết kế composite index trong PostgreSQL — tăng tốc query từ 12 giây xuống còn 45ms.
Consistent Hashing — Thuật toán phân phối tải đồng đều
Consistent Hashing giúp distributed systems thêm/xoá node mà không cần rehash toàn bộ. Từ Redis Cluster đến load balancer — tất cả đều dùng.
Table-Driven Tests trong Go — Viết test sạch, maintain dễ
Table-driven tests giúp Go tests gọn gàng, dễ thêm case mới. Học pattern này qua ví dụ thực tế và kinh nghiệm production.
JavaScript Event Loop — Microtask vs Macrotask trong async
Hiểu rõ Event Loop, Microtask và Macrotask trong JavaScript — cách Node.js và browser xử lý code bất đồng bộ.
.NET Middleware Pipeline — request đi qua đâu trước Controller?
Tìm hiểu Middleware Pipeline trong .NET — cách request HTTP chạy qua từng lớp middleware, custom middleware và exception handling thực tế.
PostgreSQL Index Types — B-tree, Hash, GiST, GIN và cách chọn
PostgreSQL có nhiều loại index hơn bạn nghĩ. Từ B-tree đến BRIN — học cách chọn đúng index cho từng loại query với EXPLAIN ANALYZE thực tế.
Docker Multi-Stage Builds — image Go từ 1GB xuống 20MB
Docker multi-stage builds giảm image Go từ 1GB xuống 20MB. Học cách build nhẹ, an toàn, nhanh với Dockerfile mẫu và kinh nghiệm production.
Redis Caching — Cache Aside, Read Through & Write Through trong production
Cache là chìa khóa performance cho hệ thống backend. Tìm hiểu 3 pattern caching phổ biến nhất với Redis: Cache Aside, Read Through, Write Through — code kèm ví dụ thực tế.
PgBouncer & Connection Pooling — vì sao app chậm dù DB vẫn xanh?
Connection pooling không chỉ là chuyện "mở nhiều kết nối". Học cách dùng PgBouncer, tune pool size đúng cách và tránh 5 sai lầm thường gặp.
Circuit Breaker Pattern — đừng để một service chết kéo sập cả hệ thống
Tìm hiểu Circuit Breaker pattern — cách ngăn chặn cascade failure trong microservices với code Go thực tế.
gRPC — Khi REST không còn đủ nhanh cho microservices
Khám phá gRPC — giao thức giao tiếp microservices nhanh hơn REST nhờ HTTP/2, Protobuf và streaming, kèm code Go thực tế.
Testcontainers — integration test với database thật, không cần mock
Testcontainers giúp bạn chạy integration test với PostgreSQL, Redis, Kafka thật trong container. Tạm biệt mock, tạm biệt những bug chỉ xuất hiện ở production.