
Homepage Blog: kiến trúc, chức năng, và pipeline publish trên AWS
Table of Contents24 sections
Vì sao chúng tôi quyết định tự xây?
Đầu năm 2026, team CMDN (Classmethod Đà Nẵng) cần một nơi để chia sẻ kiến thức, kinh nghiệm và các bài viết kỹ thuật trong nội bộ. Yêu cầu ban đầu nghe có vẻ đơn giản — nhưng khi nhìn vào các lựa chọn có sẵn, chúng tôi nhận ra không có cái nào thực sự phù hợp.
Dùng static site generator như Jekyll hay Hugo? Tác giả phải biết Git để đăng bài. Muốn thêm người viết là phải cấp quyền repo, review PR — bottleneck ngay từ đầu.
Dùng WordPress hay Ghost? Chi phí hosting cố định $9–25+/tháng dù không có ai đọc. Và quan trọng hơn: chúng tôi là một team kỹ thuật — tự xây và kiểm soát hoàn toàn stack là điều tự nhiên.
Chúng tôi quyết định tự xây. Blog chạy được trên AWS với chi phí ước tính $0.50–14/tháng tùy theo lưu lượng — gần như $0 khi không có traffic, tăng tuyến tính theo usage thực tế.
Tóm tắt nhanh
Blog CMDN kết hợp trang đọc tĩnh (nhanh, rẻ) với trang quản trị đầy đủ chức năng (viết bài, upload ảnh, xuất bản). Chức năng chia rõ phía người đọc và phía tác giả.
Bài mới sau khi đăng xuất hiện trên mạng trong khoảng 3 phút, do pipeline cập nhật chạy ngầm.
Chi phí ước tính $0.50–14 mỗi tháng tùy lượt xem. Tham chiếu thực tế: một blog tĩnh 18 tháng production trên AWS tốn khoảng $0.93/tháng (Bezdelev, Medium).
1. Chức năng chính
Blog CMDN không phải là static site generator thuần túy như Jekyll hay Hugo. Hệ thống có backend riêng với dashboard quản trị, full-text search, hệ thống tag, upload media, và Tiptap editor. Chức năng được phân tách rõ ràng thành hai nhóm:
Phía người đọc (public, không yêu cầu xác thực)
Xem danh sách bài đã xuất bản với phân trang
Đọc nội dung từng bài
Lọc bài theo tag
Tìm kiếm nội dung
Theo dõi RSS feed
Phía tác giả (yêu cầu xác thực)
Soạn thảo và chỉnh sửa bài qua WYSIWYG editor
Lưu bản nháp hoặc xuất bản
Upload và đính kèm ảnh (file tạm tự động xóa sau 24 giờ)
Quản lý tag
Xuất bản hoặc gỡ bài — hành động này kích hoạt pipeline cập nhật tự động
2. Kiến trúc tổng quan
Stack công nghệ
Layer | Công nghệ |
|---|---|
Frontend | Next.js 15 ( |
Hosting & CDN | S3 + CloudFront |
Backend | Lambda + API Gateway HTTP API |
Database | DynamoDB (2 bảng) |
Authentication | Auth0 |
Publish pipeline | SQS + GitHub Actions |
Toàn bộ hệ thống là serverless — không có EC2, không có ECS, không có server cần maintain 24/7.
Diagram kiến trúc tổng quan

Luồng dữ liệu
Reader path hoàn toàn tĩnh: CloudFront serve HTML trực tiếp từ S3, không phát sinh Lambda invocation nào. Đây là yếu tố then chốt giúp chi phí gần như bằng $0 khi traffic thấp.
Author path đi qua API Gateway → Lambda → DynamoDB. Auth0 JWT được verify tại tầng API Gateway native authorizer, không cần Lambda authorizer riêng per request — giảm latency và chi phí invocation.
Thiết kế database
DynamoDB được chia thành hai bảng với vai trò tách biệt:
Table A (Author workspace): Chứa toàn bộ draft và bài đã xuất bản. Mọi thao tác viết và chỉnh sửa đều ghi vào bảng này.
Table B (Reader store): Chỉ chứa bài đã xuất bản, phục vụ reader path.
Khi tác giả xuất bản, dữ liệu được ghi đồng thời vào cả hai bảng trong một transaction. Khi gỡ bài, bài bị xóa khỏi Table B nhưng vẫn tồn tại trong Table A. Thiết kế này đảm bảo reader query không phải scan qua bản nháp, tiết kiệm read capacity và giảm chi phí DynamoDB.
Lý do chọn HTTP API thay vì REST API
API Gateway HTTP API có giá $1.00/triệu request, so với $3.50/triệu của REST API — tiết kiệm khoảng 71% ở mức 100K page view/tháng. Blog backend không yêu cầu WAF tích hợp hay request validation phức tạp, nên HTTP API là lựa chọn đủ dùng và tối ưu chi phí.
Lý do chọn ARM64 (Graviton2) cho Lambda
AWS ghi nhận ARM64 Graviton2 giảm khoảng 20% duration cost so với x86 cho cùng workload. ARM64 hiện đã stable và là default được khuyến nghị cho Lambda function mới.
3. Pipeline publish
Vấn đề với Next.js static export
output: "export" của Next.js không hỗ trợ Incremental Static Regeneration (ISR). Bài mới xuất bản chỉ xuất hiện trên static route sau lần build và deploy kế tiếp — đây là hạn chế được xác nhận trong Next.js official docs.
Giải pháp: Lambda → SQS → GitHub Actions
CMDN giải quyết bằng pipeline bất đồng bộ:
Tác giả bấm Publish
→ Lambda ghi vào DynamoDB (Table A + Table B)
→ Lambda gửi message vào SQS queue
→ GitHub Actions lắng nghe SQS trigger
→ Next.js static export rebuild
→ S3 sync
→ CloudFront cache invalidation
→ Bài live trên CDNThời gian end-to-end từ lúc bấm Publish đến khi bài xuất hiện: khoảng 3 phút.
Diagram publish pipeline

Lý do chọn pipeline này
Tận dụng GitHub Actions free tier. GitHub cung cấp 2.000 phút free/tháng cho private repo và không giới hạn cho public repo. Mỗi rebuild tốn 1–3 phút. Với tần suất 30 bài/tháng, tổng usage khoảng 90 phút — nằm hoàn toàn trong free tier. Sử dụng AWS CodeBuild hoặc self-hosted runner sẽ phát sinh thêm $5–10/tháng mà không có lợi thế rõ ràng.
Tách biệt write path khỏi read path. SQS là queue bất đồng bộ. Lambda trả về response cho tác giả ngay khi DynamoDB write hoàn tất, không chờ rebuild. Reader path (CloudFront → S3) hoàn toàn độc lập, không bị ảnh hưởng bởi publish spike.
ISR-like behavior không cần Next.js server thường trực. Bài cũ là static HTML, không cần Lambda SSR mỗi request. Trade-off duy nhất là publish latency ~60 giây — không phù hợp với news site, nhưng hoàn toàn chấp nhận được cho blog kỹ thuật hoặc blog nội bộ.
So sánh với alternative phổ biến: Hầu hết tutorial Next.js trên AWS chọn OpenNext hoặc AWS Amplify để giả lập ISR. Approach của CMDN đánh đổi một chút UX (publish latency) để đổi lấy kiến trúc đơn giản hơn và chi phí biến đổi theo usage thực tế.
4. Chi phí ước tính theo từng service
Toàn bộ hệ thống serverless — chi phí tỉ lệ thuận với usage thực tế. Dưới đây là breakdown theo từng service ở ba mức traffic khác nhau.
Giả định tính toán
Mức | Page view/tháng | API request/tháng | Ghi chú |
|---|---|---|---|
Thấp | ~5.000 | ~10.000 | Blog nội bộ mới ra mắt |
Trung bình | ~50.000 | ~100.000 | Blog có traction |
Cao | ~500.000 | ~1.000.000 | Bài được chia sẻ rộng |
Reader path (CloudFront → S3) không phát sinh Lambda invocation — chỉ tính CloudFront transfer và S3 GET request. Author path (API Gateway → Lambda → DynamoDB) tính riêng.
Breakdown chi phí theo service
Service | Mức thấp | Mức trung bình | Mức cao | Ghi chú |
|---|---|---|---|---|
S3 (hosting static) | ~$0.02 | ~$0.05 | ~$0.23 | GET request + storage ~50MB |
CloudFront | ~$0.10 | ~$0.85 | ~$8.50 | $0.0085/GB transfer, edge Asia |
API Gateway HTTP API | ~$0.01 | ~$0.10 | ~$1.00 | $1.00/triệu request |
Lambda | ~$0.00 | ~$0.02 | ~$0.20 | Free tier 1M req; ARM64 Graviton2 |
DynamoDB | ~$0.10 | ~$0.50 | ~$2.50 | On-demand; 2 bảng tách biệt |
S3 (media upload) | ~$0.02 | ~$0.10 | ~$0.50 | Presigned URL, file tạm xóa sau 24h |
SQS | ~$0.00 | ~$0.00 | ~$0.01 | Free tier 1M request/tháng |
Auth0 | ~$0.00 | ~$0.00 | ~$0.00 | Free tier 7.500 MAU |
GitHub Actions | ~$0.00 | ~$0.00 | ~$0.00 | Free tier ~2.000 phút/tháng |
Tổng ước tính | ~$0.25–0.50 | ~$1.62–2.00 | ~$12.94–14.00 |
Lưu ý: Số liệu dựa trên AWS pricing công bố tại thời điểm triển khai (2026-Q1). Giá CloudFront tính theo edge region Asia Pacific. Lambda nằm trong free tier ở mức thấp và trung bình. DynamoDB on-demand — không phát sinh chi phí khi không có traffic.
Chi phí thực tế tham chiếu
Một blog tĩnh trên AWS sau 18 tháng production ghi nhận chi phí trung bình khoảng $0.93/tháng (Bezdelev, Medium, 2026) — phù hợp với ước tính mức thấp của chúng tôi. Blog CMDN có thêm Lambda và DynamoDB cho author path, nên thực tế sẽ cao hơn một chút tùy mức độ tác giả sử dụng dashboard.
So sánh với alternative
Setup CMDN | Ghost Pro | Wordpress | |
|---|---|---|---|
Traffic thấp | ~$0.50/tháng | $9/tháng | $25/tháng |
Traffic trung bình | ~$2/tháng | $9/tháng | $25/tháng |
Traffic cao | ~$14/tháng | $25/tháng | $25/tháng |
Chi phí khi zero traffic | ~$0 | $9/tháng (fixed) | $25/tháng (fixed) |
Setup serverless có lợi thế rõ ràng ở giai đoạn đầu khi traffic thấp. Ở mức traffic cao (~500K page view/tháng), khoảng cách thu hẹp lại — nhưng chúng tôi vẫn kiểm soát hoàn toàn infrastructure và không bị vendor lock-in.
5. Kết luận — khi nào nên chọn setup này
Khi nào nên chọn setup này
Setup phù hợp với:
Blog công ty, blog kỹ thuật, hoặc blog sản phẩm
Team có kỹ năng AWS và muốn kiểm soát infrastructure
Khi nào không nên chọn
News site hoặc nội dung realtime: Publish latency 60 giây không chấp nhận được.
Team không có dev rành AWS: Chi phí setup và vận hành về kiến thức cao hơn dùng Ghost hay WordPress.
Cần CMS thân thiện với marketer: WYSIWYG editor tự xây không thể cạnh tranh với CMS chuyên dụng về UX.
Tham khảo
Bezdelev, Cost Breakdown for a Static Website on AWS After 18 Months in Production, Medium, 2026 — https://medium.com/@bezdelev/cost-breakdown-for-a-static-website-on-aws-after-18-months-in-production-d97a932d2d25
AWS, API Gateway Pricing — https://aws.amazon.com/api-gateway/pricing/
AWS, Lambda Functions Powered by AWS Graviton2 Processor — https://aws.amazon.com/blogs/aws/aws-lambda-functions-powered-by-aws-graviton2-processor-run-your-functions-on-arm-and-get-up-to-34-better-price-performance/
AWS, CloudFront Pricing — https://aws.amazon.com/cloudfront/pricing/
Next.js, Single Page Applications guide — https://nextjs.org/docs/app/guides/single-page-applications
GitHub, Pricing — Actions free minutes — https://github.com/pricing
ScyllaDB, Why AWS DynamoDB Costs Catch Teams Off Guard, 2025 — https://www.scylladb.com/2025/07/22/why-aws-dynamodb-costs-catch-teams-off-guard/