<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Rate Limiting on miti99</title><link>https://miti99.com/tags/rate-limiting/</link><description>Recent content in Rate Limiting on miti99</description><generator>Hugo -- gohugo.io</generator><language>vi</language><lastBuildDate>Wed, 08 Jul 2026 09:22:18 +0700</lastBuildDate><atom:link href="https://miti99.com/tags/rate-limiting/index.xml" rel="self" type="application/rss+xml"/><item><title>Newsletter #89</title><link>https://miti99.com/post/2026/03/14/</link><pubDate>Sat, 14 Mar 2026 00:00:00 +0700</pubDate><guid>https://miti99.com/post/2026/03/14/</guid><description>&lt;p&gt;&lt;em&gt;Mời bạn thưởng thức Newsletter #89.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="hybrid-quota-linear-rate-limiter"&gt;&lt;a class="link" href="https://dotat.at/@/2026-01-12-hqlr.html" target="_blank" rel="noopener"
&gt;Hybrid Quota-Linear Rate Limiter&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Tony Finch phân tích một vấn đề phổ biến với các thuật toán giới hạn tốc độ (rate limiter) tuyến tính như leaky bucket và GCRA: chúng có xu hướng &amp;ldquo;hào phóng&amp;rdquo; hơn mức cần thiết trong giai đoạn khởi động, cho phép client gửi khoảng &lt;code&gt;q*a/(a-1)&lt;/code&gt; yêu cầu trước khi bị giới hạn khi hoạt động ở tốc độ gấp &lt;code&gt;a&lt;/code&gt; lần cho phép.&lt;/p&gt;
&lt;p&gt;Để giải quyết vấn đề này, tác giả đề xuất một thuật toán lai hoạt động ở hai chế độ: &lt;strong&gt;chế độ bursty&lt;/strong&gt; dành cho các client có lưu lượng thấp, cho phép gửi theo đợt nhưng giới hạn tối đa một quota token mỗi cửa sổ thời gian; và &lt;strong&gt;chế độ smooth&lt;/strong&gt; dành cho client có lưu lượng cao, buộc phân phối yêu cầu đều đặn hơn. Thuật toán tự chuyển đổi giữa hai chế độ khi client tiêu hết quota hoặc khi bucket phục hồi hoàn toàn. Cách tiếp cận này sử dụng ít bộ nhớ hơn so với phương pháp quota-reset, đồng thời kiểm soát quota chặt chẽ hơn so với rate limiter tuyến tính thuần túy.&lt;/p&gt;
&lt;p&gt;Tuy nhiên, điểm thú vị là tác giả cuối cùng khuyên &lt;strong&gt;không nên&lt;/strong&gt; dùng thuật toán phức tạp này. Thay vào đó, hãy cân nhắc lại bài toán để có thể sử dụng một rate limiter tuyến tính đơn giản như GCRA — vì việc đo tốc độ trung bình theo thời gian dài tự nhiên khuyến khích client hoạt động mượt mà hơn.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rate limiter tuyến tính (GCRA, leaky bucket) có thể cho phép nhiều yêu cầu hơn dự kiến trong giai đoạn khởi động&lt;/li&gt;
&lt;li&gt;Thuật toán lai kết hợp chế độ bursty và smooth để kiểm soát chặt chẽ hơn&lt;/li&gt;
&lt;li&gt;Đơn giản hóa vẫn là ưu tiên hàng đầu: GCRA đủ tốt cho hầu hết các trường hợp thực tế&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="go-is-the-best-language-for-ai-agents"&gt;&lt;a class="link" href="https://getbruin.com/blog/go-is-the-best-language-for-agents/" target="_blank" rel="noopener"
&gt;Go is the Best Language for AI Agents&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Burak Karakan — CEO của Bruin, người có 8 năm kinh nghiệm lập trình Go — lập luận rằng Go là ngôn ngữ lý tưởng để phát triển phần mềm bằng AI agent. Lý do cốt lõi xuất phát từ bản chất của ngôn ngữ biên dịch: khi agent tạo ra mã nguồn Go bị lỗi, trình biên dịch sẽ trả về thông báo lỗi rõ ràng ngay lập tức, tạo vòng phản hồi nhanh và chính xác để agent tự sửa lỗi. Điều này khác hoàn toàn so với Python hay JavaScript — vốn chỉ báo lỗi khi chạy thực tế.&lt;/p&gt;
&lt;p&gt;Hệ thống kiểu tĩnh của Go cũng là một lợi thế lớn: agent có thể xác minh tính đúng đắn của mã trước khi chạy, thay vì phải phụ thuộc vào các bài kiểm thử thủ công. So với Rust — ngôn ngữ biên dịch khác — Go vẫn chiếm ưu thế nhờ cú pháp đơn giản hơn, tốc độ biên dịch nhanh hơn, và lượng mã Go trong dữ liệu huấn luyện của các mô hình AI lớn hơn đáng kể. Ngoài ra, bộ kiểm thử của Go chạy cực nhanh và hoạt động nhất quán trên mọi hệ điều hành, giúp các background agent có thể xác nhận kết quả công việc mà không phụ thuộc vào môi trường chạy cụ thể.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go biên dịch nhanh và báo lỗi rõ ràng giúp AI agent có vòng phản hồi ngắn để tự sửa lỗi&lt;/li&gt;
&lt;li&gt;Kiểu tĩnh và cú pháp đơn giản giảm thiểu sai sót trong mã do agent tạo ra&lt;/li&gt;
&lt;li&gt;Go chạy nhất quán trên mọi nền tảng — lợi thế lớn cho background agent và môi trường sandbox&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="your-agent-needs-a-harness-not-a-framework"&gt;&lt;a class="link" href="https://x.com/djfarrelly/status/2028556984396452250" target="_blank" rel="noopener"
&gt;Your Agent Needs a Harness, Not a Framework&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Dan Farrelly từ Inngest.com đưa ra một góc nhìn sắc bén về kiến trúc AI agent: thay vì dùng framework, agent cần một &amp;ldquo;harness&amp;rdquo; — lớp kết nối, bảo vệ và điều phối các thành phần mà không làm thay công việc của chúng. Trong mọi ngành kỹ thuật, harness đều có vai trò như vậy: dây điện nối các cảm biến, test harness cung cấp giàn giáo kiểm thử, dây an toàn giữ bạn khi ngã. Agent runtime cũng cần điều tương tự.&lt;/p&gt;
&lt;p&gt;Vấn đề hiện tại là mỗi framework agent lại tự xây dựng lại từ đầu: retry logic, lưu trạng thái, job queue, định tuyến sự kiện. Thay vào đó, hãy dùng hạ tầng event-driven bền vững đã sẵn có — mỗi lần gọi LLM hay công cụ trở thành một &amp;ldquo;step&amp;rdquo; có thể thử lại độc lập. Nếu tiến trình chết ở vòng lặp thứ năm, bốn vòng trước đã được lưu lại. Nhóm tác giả đã xây dựng &lt;strong&gt;Utah&lt;/strong&gt; (Universally Triggered Agent Harness) để minh chứng: một agent hội thoại qua Telegram/Slack với công cụ, bộ nhớ, ủy quyền sub-agent và khả năng chịu lỗi — chỉ dùng Inngest, không framework. Bài học quan trọng rút ra: quản lý ngữ cảnh (context management) mới là thử thách thực sự, không phải việc gọi LLM.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Agent cần &amp;ldquo;harness&amp;rdquo; để xử lý retry, trạng thái, concurrency — không phải thêm framework&lt;/li&gt;
&lt;li&gt;Mỗi lần gọi LLM/công cụ là một step độc lập, có thể thử lại mà không mất kết quả trước&lt;/li&gt;
&lt;li&gt;Quản lý ngữ cảnh (cắt bớt, nén lịch sử, cảnh báo ngân sách) là thách thức lớn nhất khi xây agent thực tế&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="an-interactive-intro-to-quadtrees"&gt;&lt;a class="link" href="https://growingswe.com/blog/quadtrees" target="_blank" rel="noopener"
&gt;An Interactive Intro to Quadtrees&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết tương tác giải thích quadtree — cấu trúc dữ liệu dùng để tìm kiếm không gian 2D hiệu quả. Vấn đề đặt ra: khi xây dựng ứng dụng bản đồ với hàng triệu địa điểm, cách đơn giản nhất là tính khoảng cách từ vị trí người dùng đến từng điểm rồi lọc ra những điểm đủ gần — nhưng với hàng triệu điểm, cách này quá chậm.&lt;/p&gt;
&lt;p&gt;Quadtree giải quyết bài toán bằng cách chia không gian thành 4 ô con khi một ô chứa quá nhiều điểm (vượt ngưỡng capacity), tạo thành cây phân cấp. Khi truy vấn, chỉ cần đệ quy vào các ô giao với vùng tìm kiếm — bỏ qua hoàn toàn phần còn lại. Tham số capacity điều chỉnh sự cân bằng: capacity thấp tạo cây sâu, bỏ qua nhiều vùng hơn nhưng tốn bộ nhớ; capacity cao tạo cây nông, tiết kiệm bộ nhớ nhưng mỗi ô cần duyệt tuyến tính nhiều điểm hơn. Ngoài tìm kiếm địa lý (Uber dùng để tìm tài xế gần nhất), quadtree còn ứng dụng trong phát hiện va chạm game (broad-phase collision detection) và nén ảnh theo vùng.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Quadtree chia không gian 2D thành 4 ô con đệ quy, giúp bỏ qua vùng không liên quan khi truy vấn&lt;/li&gt;
&lt;li&gt;Tham số capacity (thường từ 4–16) ảnh hưởng trực tiếp đến độ sâu cây và hiệu năng truy vấn&lt;/li&gt;
&lt;li&gt;Ứng dụng thực tế: tìm kiếm địa lý, phát hiện va chạm trong game, nén ảnh theo vùng&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="agentic-engineering-patterns"&gt;&lt;a class="link" href="https://simonwillison.net/guides/agentic-engineering-patterns/" target="_blank" rel="noopener"
&gt;Agentic Engineering Patterns&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Simon Willison — tác giả blog kỹ thuật nổi tiếng — ra mắt một hướng dẫn toàn diện về các mẫu thiết kế (pattern) khi làm việc với AI agent trong lập trình. Điều đáng chú ý là hướng dẫn phân biệt rõ ràng giữa &amp;ldquo;agentic engineering&amp;rdquo; và &amp;ldquo;vibe coding&amp;rdquo;: vibe coding là để LLM viết mã mà không cần giám sát, còn agentic engineering là kỹ sư chuyên nghiệp dùng agent để khuếch đại chuyên môn sẵn có của mình — không phải thay thế nó.&lt;/p&gt;
&lt;p&gt;Một số pattern nổi bật: &lt;strong&gt;&amp;ldquo;Viết mã giờ rất rẻ&amp;rdquo;&lt;/strong&gt; — chi phí sinh mã gần như bằng không, buộc phải định nghĩa lại &amp;ldquo;mã tốt&amp;rdquo; là mã có kiểm thử, tài liệu, xử lý lỗi đúng chuẩn; &lt;strong&gt;&amp;ldquo;Tích lũy những gì bạn đã biết làm&amp;rdquo;&lt;/strong&gt; — duy trì kho ví dụ hoạt động được (blog, repo, POC) để dùng làm đầu vào cho agent, vì biết rằng điều gì đó khả thi khác với đã tự mình làm được; &lt;strong&gt;&amp;ldquo;Red/green TDD&amp;rdquo;&lt;/strong&gt; — viết kiểm thử trước, xác nhận kiểm thử thất bại, rồi mới triển khai, đảm bảo agent tạo ra mã đúng chức năng và tối giản. Hướng dẫn được cập nhật liên tục mỗi tuần với 1–2 chương mới.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Agentic engineering là khuếch đại chuyên môn kỹ sư, không phải để LLM viết mã không kiểm soát&lt;/li&gt;
&lt;li&gt;Tích lũy ví dụ hoạt động được là tài sản nghề nghiệp quan trọng khi làm việc với agent&lt;/li&gt;
&lt;li&gt;Red/green TDD giúp agent tạo mã tối giản, đúng chức năng và có lưới an toàn kiểm thử&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="things-i-miss-about-spring-boot-after-switching-to-go"&gt;&lt;a class="link" href="https://sushantdhiman.dev/things-i-miss-about-spring-boot-after-switching-to-go/" target="_blank" rel="noopener"
&gt;Things I Miss About Spring Boot After Switching to Go&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Sushant Dhiman chia sẻ góc nhìn thực tế sau khi chuyển từ Spring Boot sang Go. Dù Go có nhiều ưu điểm, tác giả thừa nhận có những thứ trong Spring Boot mà Go chưa thể thay thế dễ dàng. Trước hết là triết lý &amp;ldquo;batteries included&amp;rdquo; của Spring Boot — hầu hết tính năng cần thiết cho môi trường production đều có sẵn và tích hợp chặt chẽ với nhau.&lt;/p&gt;
&lt;p&gt;Cụ thể, tác giả nhớ nhất: &lt;strong&gt;Dependency Injection&lt;/strong&gt; tự động qua annotation (&lt;code&gt;@Service&lt;/code&gt;, &lt;code&gt;@Autowired&lt;/code&gt;) thay vì phải tự nối dây thủ công qua constructor trong Go; &lt;strong&gt;validation khai báo&lt;/strong&gt; với &lt;code&gt;@NotNull&lt;/code&gt;, &lt;code&gt;@Email&lt;/code&gt; thay vì viết điều kiện kiểm tra thủ công; và hệ sinh thái trưởng thành gồm Spring Security (xác thực JWT, OAuth), Spring Data (tự sinh câu truy vấn từ tên phương thức), Spring Boot Actuator (giám sát sức khỏe tích hợp sẵn), Spring Cloud (hỗ trợ microservices). Go có các thư viện tương đương nhưng thiếu sự gắn kết thống nhất trong một framework duy nhất.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Spring Boot tích hợp sẵn dependency injection, validation khai báo và hệ sinh thái production-ready&lt;/li&gt;
&lt;li&gt;Go theo triết lý tối giản — linh hoạt hơn nhưng đòi hỏi tự lắp ráp nhiều thành phần hơn&lt;/li&gt;
&lt;li&gt;Cả hai có đánh đổi rõ ràng: Spring Boot tiện lợi hơn, Go đơn giản và hiệu năng cao hơn&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="design-first-collaboration-with-ai"&gt;&lt;a class="link" href="https://martinfowler.com/articles/reduce-friction-ai/design-first-collaboration.html" target="_blank" rel="noopener"
&gt;Design-First Collaboration with AI&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết từ martinfowler.com giới thiệu phương pháp cộng tác &amp;ldquo;design-first&amp;rdquo; với AI để tránh &amp;ldquo;Implementation Trap&amp;rdquo; — bẫy mà AI sinh mã quá nhanh khiến các quyết định thiết kế quan trọng bị chôn vùi trong mã nguồn, và lập trình viên chỉ phát hiện ra bất đồng khi đọc lại mã — lúc đó đã quá tốn kém để sửa.&lt;/p&gt;
&lt;p&gt;Giải pháp là khung năm cấp độ, không được viết mã cho đến khi cấp độ 5 được phê duyệt: &lt;strong&gt;(1) Capabilities&lt;/strong&gt; — yêu cầu cốt lõi; &lt;strong&gt;(2) Components&lt;/strong&gt; — các khối xây dựng và trừu tượng; &lt;strong&gt;(3) Interactions&lt;/strong&gt; — luồng dữ liệu và giao tiếp; &lt;strong&gt;(4) Contracts&lt;/strong&gt; — chữ ký hàm và interface; &lt;strong&gt;(5) Implementation&lt;/strong&gt; — viết mã. Mỗi cấp độ chỉ kiểm tra một loại quyết định, giảm tải nhận thức đáng kể so với việc xem xét tất cả cùng lúc. Mức độ phức tạp quyết định điểm bắt đầu — tiện ích đơn giản có thể bắt đầu từ cấp 4, tính năng phức tạp bắt đầu từ cấp 1.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Đừng để AI viết mã trước khi thống nhất thiết kế — phát hiện bất đồng sớm rẻ hơn rất nhiều&lt;/li&gt;
&lt;li&gt;Khung 5 cấp độ tách biệt từng loại quyết định thiết kế, giảm tải nhận thức khi xem xét&lt;/li&gt;
&lt;li&gt;Phương pháp này tạo điều kiện tự nhiên cho TDD và ngăn chặn &amp;ldquo;technical debt injection&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-two-kinds-of-error"&gt;&lt;a class="link" href="https://evanhahn.com/the-two-kinds-of-error/" target="_blank" rel="noopener"
&gt;The Two Kinds of Error&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Evan Hahn đề xuất một cách phân loại lỗi đơn giản nhưng hữu ích: lỗi &lt;strong&gt;expected&lt;/strong&gt; (có thể xảy ra trong vận hành bình thường, không phải lỗi của lập trình viên) và lỗi &lt;strong&gt;unexpected&lt;/strong&gt; (chỉ xảy ra khi có bug). Lỗi expected bao gồm: đầu vào của người dùng không hợp lệ, mất kết nối mạng, thiếu quyền truy cập — đây là lỗi có thể phục hồi, nên trả về kết quả lỗi và ghi log ở mức &lt;code&gt;WARN&lt;/code&gt; hoặc &lt;code&gt;INFO&lt;/code&gt;. Lỗi unexpected bao gồm: vi phạm assertion, logic sai, dependency chưa khởi tạo — đây là dấu hiệu của bug thực sự, nên log ở mức &lt;code&gt;ERROR&lt;/code&gt; hoặc &lt;code&gt;FATAL&lt;/code&gt;, thậm chí nên để chương trình crash hoàn toàn.&lt;/p&gt;
&lt;p&gt;Ranh giới giữa hai loại phụ thuộc vào ngữ cảnh: ứng dụng thử nghiệm có thể coi mọi lỗi là unexpected, hệ thống quan trọng (tàu vũ trụ) phải coi gần mọi thứ đều có thể xảy ra. Điều quan trọng là lập trình viên phải &lt;strong&gt;có ý thức&lt;/strong&gt; phân loại từng lỗi thay vì xử lý tất cả theo cùng một cách.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lỗi expected (mạng, đầu vào người dùng) nên được phục hồi và log WARN/INFO&lt;/li&gt;
&lt;li&gt;Lỗi unexpected (bug, logic sai) nên log ERROR/FATAL và có thể crash chương trình&lt;/li&gt;
&lt;li&gt;Phân loại có ý thức giúp thiết kế xử lý lỗi rõ ràng và đúng mức độ nghiêm trọng&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="secure-go-error-handling-best-practices"&gt;&lt;a class="link" href="https://blog.jetbrains.com/go/2026/03/02/secure-go-error-handling-best-practices/" target="_blank" rel="noopener"
&gt;Secure Go Error Handling Best Practices&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Blog JetBrains GoLand tập trung vào một khía cạnh thường bị bỏ qua: xử lý lỗi an toàn bảo mật trong Go. Nguyên tắc cốt lõi là &lt;strong&gt;tách biệt thông tin nội bộ và thông tin công khai&lt;/strong&gt; — tạo kiểu lỗi tùy chỉnh chứa cả thông báo nội bộ (chi tiết kỹ thuật cho lập trình viên) và thông báo công khai (thông báo an toàn cho người dùng), tránh việc lỗi nội bộ bị serialized ra HTTP response.&lt;/p&gt;
&lt;p&gt;Các thực hành quan trọng: dùng &lt;strong&gt;builder pattern&lt;/strong&gt; để kiểm soát trường metadata nào được ghi log, tránh ghi toàn bộ đối tượng request có thể chứa mật khẩu hay token; dùng &lt;strong&gt;opaque wrapping&lt;/strong&gt; thay vì &lt;code&gt;fmt.Errorf&lt;/code&gt; khi không muốn lộ chi tiết triển khai cho phía gọi; và khi truyền lỗi qua ranh giới dịch vụ, chuyển đổi sang lỗi chuẩn hóa (gRPC codes, JSON format), không bao giờ để lỗi do AI sinh ra tiếp cận API công khai. Logging nên dùng &lt;code&gt;log/slog&lt;/code&gt; với structured logging và implement interface redaction cho các trường nhạy cảm.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tách lỗi thành thông báo nội bộ (kỹ thuật) và công khai (an toàn) để tránh rò rỉ thông tin&lt;/li&gt;
&lt;li&gt;Kiểm soát chặt metadata được ghi log, không ghi toàn bộ request object&lt;/li&gt;
&lt;li&gt;API công khai chỉ trả về thông báo tĩnh, định nghĩa sẵn — không bao giờ lỗi được sinh động&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ai-coding-tools-java--compounding-engineering"&gt;&lt;a class="link" href="https://www.the-main-thread.com/p/ai-coding-tools-java-compounding-engineering" target="_blank" rel="noopener"
&gt;AI Coding Tools, Java &amp;amp; Compounding Engineering&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết tổng hợp từ buổi nói chuyện tại NDC Manchester 2025, với luận điểm cốt lõi: &amp;ldquo;Nếu AI tạo ra mã tệ cho bạn, đó thường là vấn đề workflow, không phải vấn đề mô hình.&amp;rdquo; Phương pháp được đề xuất là &lt;strong&gt;Compounding Engineering&lt;/strong&gt; — huấn luyện AI như người cộng tác theo thời gian, tương tự onboard lập trình viên junior.&lt;/p&gt;
&lt;p&gt;Các yếu tố chính: xóa chat thường xuyên và lưu quyết định kiến trúc vào file markdown (như &lt;code&gt;CLAUDE.md&lt;/code&gt;) thay vì cố duy trì ngữ cảnh trong một cuộc trò chuyện dài; cập nhật &amp;ldquo;living rule files&amp;rdquo; mỗi khi sửa bug để lỗi không tái diễn; lên kế hoạch trước khi viết mã để phát hiện giả định sai ngay từ đầu; chia tính năng thành các tác vụ nhỏ, tập trung một trách nhiệm. Kỹ sư senior đóng góp giá trị qua &lt;strong&gt;taste&lt;/strong&gt; — khả năng đánh giá kiến trúc và đánh đổi, điều mà AI giỏi sinh mã nhưng yếu phán xét chất lượng. Kết quả tích lũy theo thời gian; không đầu tư vào workflow thì chỉ có &amp;ldquo;mediocrity nhanh hơn&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mã AI kém chất lượng thường do workflow kém, không phải do mô hình&lt;/li&gt;
&lt;li&gt;Lưu quyết định kiến trúc vào file markdown, cập nhật khi sửa bug để kiến thức tích lũy&lt;/li&gt;
&lt;li&gt;Giá trị của kỹ sư senior nằm ở khả năng phán xét kiến trúc — thứ AI chưa làm tốt&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="yaml-that"&gt;&lt;a class="link" href="https://lab174.com/blog/202601-yaml-norway/" target="_blank" rel="noopener"
&gt;YAML? That&amp;rsquo;s Norway Problem&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết khám phá một lỗi phân tích cú pháp thú vị trong YAML: mã quốc gia &lt;code&gt;NO&lt;/code&gt; (Na Uy) bị các trình phân tích cú pháp phổ biến chuyển thành giá trị boolean &lt;code&gt;false&lt;/code&gt; thay vì chuỗi ký tự. Nguyên nhân là YAML xử lý một số từ tiếng Anh như &lt;code&gt;yes/no&lt;/code&gt;, &lt;code&gt;true/false&lt;/code&gt;, &lt;code&gt;on/off&lt;/code&gt; dưới dạng giá trị boolean — tính năng này được giới thiệu từ YAML v1.0 (2004) nhằm làm cho tệp cấu hình dễ đọc hơn.&lt;/p&gt;
&lt;p&gt;Dù YAML v1.2 (2009) đã loại bỏ hành vi này để tương thích với JSON, hầu hết các thư viện phổ biến như PyYAML và LibYAML vẫn triển khai theo đặc tả v1.1 — tạo ra khoảng cách lớn giữa tiêu chuẩn và thực tế sau hơn 15 năm. Người dùng có thể tránh vấn đề này bằng cách đặt chuỗi trong dấu ngoặc kép (&lt;code&gt;&amp;quot;NO&amp;quot;&lt;/code&gt;), dùng thẻ kiểu tường minh (&lt;code&gt;!!str&lt;/code&gt;), hoặc chuyển sang thư viện tương thích v1.2 như &lt;code&gt;ruamel.yaml&lt;/code&gt; hay &lt;code&gt;yq&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NO&lt;/code&gt; trong YAML bị hiểu là &lt;code&gt;false&lt;/code&gt; do quy tắc boolean từ đặc tả v1.1&lt;/li&gt;
&lt;li&gt;YAML v1.2 đã sửa lỗi này từ năm 2009 nhưng hầu hết thư viện chưa cập nhật&lt;/li&gt;
&lt;li&gt;Giải pháp: dùng dấu ngoặc kép, thẻ &lt;code&gt;!!str&lt;/code&gt;, hoặc thư viện tương thích v1.2&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Bài viết đã được review và cập nhật bởi Claude Code với Opus 4.7 (1M context).&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Newsletter #87</title><link>https://miti99.com/post/2026/03/02/</link><pubDate>Mon, 02 Mar 2026 00:00:00 +0700</pubDate><guid>https://miti99.com/post/2026/03/02/</guid><description>&lt;p&gt;&lt;em&gt;Mời bạn thưởng thức Newsletter #87.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="on-cognitive-debt"&gt;&lt;a class="link" href="https://www.natemeyvis.com/on-cognitive-debt/" target="_blank" rel="noopener"
&gt;On cognitive debt&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết thảo luận về khái niệm &amp;ldquo;cognitive debt&amp;rdquo; (nợ nhận thức) trong bối cảnh phát triển phần mềm được hỗ trợ bởi AI. Tác giả lập luận rằng mặc dù AI-generated codebases có thể tạo ra cognitive debt, nhưng thực tế tình trạng này thường tồn tại ở mức độ cao hơn trong các codebase truyền thống. Người ta thường không nhận ra điều này vì nhiều hoạt động kỹ thuật tiêu chuẩn thực chất là quản lý cognitive debt hoặc tránh né nó với chi phí khổng lồ.&lt;/p&gt;
&lt;p&gt;Tác giả chỉ ra ba luận điểm chính: một là, khi kiểm soát theo quy mô dự án, cognitive debt trong codebase AI thường không tồi hơn so với các phương pháp truyền thống; hai là, nhiều công việc kỹ thuật được &amp;ldquo;bình thường hóa&amp;rdquo; thực chất là quản lý cognitive debt không cần thiết; và ba là, những người sử dụng AI tốt nhất đã khá giỏi trong việc tránh cognitive debt, và chúng ta sẽ ngày càng cải thiện.&lt;/p&gt;
&lt;p&gt;Bài viết cũng đề xuất một số kỹ thuật để giảm thiểu cognitive debt khi làm việc với AI: nhấn mạnh tính đóng gói (encapsulation), mô tả kỹ lưỡng các subsystem và interface, thực hiện các refactoring quy mô lớn với sự hỗ trợ của AI, và cải thiện bộ test ở những nơi cognitive debt đang xuất hiện.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI không làm gia tăng cognitive debt khi so sánh với các phương pháp phát triển truyền thống ở cùng quy mô&lt;/li&gt;
&lt;li&gt;Nhiều công việc kỹ thuật hàng ngày thực chất là hệ quả của việc đã đưa ra sự phức tạp không cần thiết&lt;/li&gt;
&lt;li&gt;Sử dụng AI một cách khéo léo có thể giúp giảm thiểu cognitive debt thông qua các kỹ thuật như encapsulation và refactoring&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="why-i"&gt;&lt;a class="link" href="https://davidoks.blog/p/why-im-not-worried-about-ai-job-loss" target="_blank" rel="noopener"
&gt;Why I&amp;rsquo;m not worried about AI job loss&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết phản biện lại nỗi lo ngại phổ biến về việc AI sẽ gây ra mất việc làm hàng loạt. Tác giả lập luận rằng chúng ta không đang ở trong một khoảnh khắc giống như tháng 2 năm 2020 trước khi COVID bùng phát, và rằng những dự báo về sự sụp đổ của thị trường lao động là không có cơ sở. Bài viết phân tích tại sao sự thay thế lao động bằng AI sẽ diễn ra chậm hơn và ít gây tổn hại hơn nhiều người nghĩ.&lt;/p&gt;
&lt;p&gt;Tác giả giải thích ba luận điểm chính. Thứ nhất, thay thế lao động dựa trên lợi thế so sánh chứ không phải lợi thế tuyệt đối — ngay cả khi AI có thể thực hiện mọi tốt hơn con người, sự kết hợp giữa người và AI vẫn có thể tạo ra kết quả tốt hơn. Thứ hai, thế giới đầy rẫy các &amp;ldquo;nút thắt&amp;rdquo; do con người tạo ra — luật pháp, văn hóa doanh nghiệp, chính trị, và sự kháng cự thay đổi — những thứ này sẽ đảm bảo rằng con người vẫn cần thiết trong thời gian dài. Thứ ba, nhu cầu đối với hầu hết các sản phẩm mà con người tạo ra có tính đàn hồi cao hơn chúng ta nhận thức, và hiệu quả năng suất thường bị nuốt chửng bởi tăng trưởng nhu cầu (nghịch lý Jevons).&lt;/p&gt;
&lt;p&gt;Tác giả kết luận rằng người bình thường sẽ không có gì phải lo lắng về AI. Sự chuyển đổi kinh tế sẽ diễn ra từ từ và nhẹ nhàng hơn nhiều người nghĩ. Mặc dù một số người sẽ phải điều chỉnh, nhưng phần lớn mọi người sẽ ổn. Mối nguy hiểm thực sự không phải là tác động kinh tế của AI, mà là sự phản ứng chính trị và xã hội từ việc gây hoang mang cho công chúng một cách không cần thiết.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI sẽ không thay thế lao động con người ngay lập tức vì thế giới vẫn phụ thuộc vào các nút thắt do con người tạo ra&lt;/li&gt;
&lt;li&gt;Sự kết hợp giữa người và AI thường hiệu quả hơn AI hoạt động độc lập&lt;/li&gt;
&lt;li&gt;Nhu cầu đối với sản phẩm con người tạo ra có tính đàn hồi cao, dẫn đến nghịch lý Jevons&lt;/li&gt;
&lt;li&gt;Nguy cơ thực sự là sự phản ứng chính trị chống AI từ việc gây hoang mang công chúng&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="why-i-don"&gt;&lt;a class="link" href="https://honnibal.dev/blog/ai-bubble" target="_blank" rel="noopener"
&gt;Why I don&amp;rsquo;t think AI is a bubble&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết phản biện lại quan điểm cho rằng AI đang trong một &amp;ldquo;bong bóng&amp;rdquo; sắp vỡ. Tác giả Matthew Honnibal — người tạo ra thư viện spaCy NLP — lập luận rằng hiệu suất của AI có thể sẽ không đạt đến đỉnh cao, ít nhất là những lập luận phổ biến về việc tại sao nó sẽ đạt đỉnh là không thuyết phục. Ông giải thích sự phát triển của các mô hình &amp;ldquo;reasoning&amp;rdquo; và cách chúng hoạt động khác biệt so với các mô hình completion đơn thuần.&lt;/p&gt;
&lt;p&gt;Tác giả phân tích lịch sử phát triển từ GPT-1 đến các mô hình reasoning hiện đại như Claude Opus và GPT-5. Sự thay đổi chính là kết hợp giữa generative AI và deep reinforcement learning — cho phép mô hình tự tạo ra các bước trung gian để giải quyết vấn đề thay vì chỉ dự đoán từ tiếp theo. Logic là công việc, ngay cả trong hệ thống thuần túy, và suy luận không bao giờ miễn phí. Các mô hình reasoning sử dụng reinforcement learning để học các chiến lược chung cho việc giải quyết vấn đề.&lt;/p&gt;
&lt;p&gt;Tác giả chỉ ra hai đòn bẩy mới để cải thiện LLMs: cho phép mô hình chạy lâu hơn (làm nhiều reasoning hơn) và thêm nhiều reinforcement learning hơn. Không có giới hạn dữ liệu rõ ràng cho reinforcement learning vì suy luận là một hàm một chiều — dễ dàng nhận diện một con dẫn đến kết luận đúng hơn là tạo ra nó. Mặc dù tác giả không tin tưởng vào OpenAI cụ thể, ông tin rằng các trung tâm dữ liệu sẽ được sử dụng hiệu quả.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hiệu suất AI có thể sẽ không đạt đỉnh vì các mô hình reasoning có hai đòn bẩy mới: thời gian chạy và reinforcement learning&lt;/li&gt;
&lt;li&gt;Các mô hình reasoning kết hợp generative AI với reinforcement learning để học các chiến lược giải quyết vấn đề chung&lt;/li&gt;
&lt;li&gt;Logic và suy luận đòi hỏi công việc tính toán, không bao giờ miễn phí ngay cả trong hệ thống thuần túy&lt;/li&gt;
&lt;li&gt;Không có giới hạn dữ liệu cho reinforcement learning vì mô hình có thể tự cải thiện thông qua việc nhận diện các con suy luận thành công&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="i-guess-i-kinda-get-why-people-hate-ai"&gt;&lt;a class="link" href="https://anthony.noided.media/blog/ai/programming/2026/02/14/i-guess-i-kinda-get-why-people-hate-ai.html" target="_blank" rel="noopener"
&gt;I guess I kinda get why people hate AI&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Tác giả, một lập trình viên đang làm việc tại Hawaii, chia sẻ suy nghĩ về lý do tại sao mọi người bắt đầu ghét AI mặc dù bản thân ông vẫn sử dụng và đánh giá cao công nghệ này. Bài viết bắt đầu với nỗi lo ngại của tác giả về việc liệu công việc mới của ông có phải là công việc cuối cùng hay không, một sự thay đổi trong tư duy so với trước đây khi ông chỉ lo lắng về việc liệu mình có &lt;em&gt;cần&lt;/em&gt; làm việc hay không.&lt;/p&gt;
&lt;p&gt;Tác giả chỉ ra nhiều lý do khiến &amp;ldquo;vibe&amp;rdquo; của AI hiện tại rất tồi tệ. Thứ nhất, những người đứng đầu các công ty AI liên tục marketing sản phẩm của họ bằng cách đe dọa rằng AI sẽ lấy đi việc làm của mọi người, điều mà tác giả mô tả là &amp;ldquo;hoàn toàn điên rồ&amp;rdquo;. Thứ hai, AI hiện nay rất hữu ích cho việc tạo ra nội dung rác — sinh viên dùng để gian lận, video giả về Elon Musk, và các video kỳ lạ trên TikTok. Thứ ba, AI gây ra các vấn đề thực tế như giá RAM tăng cao và các chương trình bug bounty bị ngừng lại vì quá nhiều báo cáo sai từ AI.&lt;/p&gt;
&lt;p&gt;Mặc dù tác giả vẫn tin rằng AI sẽ rất hữu ích trong tương lai và ông vẫn tiếp tục sử dụng nó, ông lo ngại rằng các công ty AI dường như không quan tâm đến việc giảm thiểu các tác động tiêu cực của sản phẩm họ. Tác giả đề xuất một số giải pháp như watermarking nội dung AI, chặn misinformation hơn nữa trên YouTube, và cho phép các dự án open-source yêu cầu không bị AI quét lỗ hổng.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Các CEO AI đang marketing bằng cách đe dọa người dùng thay vì giới thiệu lợi ích, một chiến lược &amp;ldquo;hoàn toàn điên rồ&amp;rdquo;&lt;/li&gt;
&lt;li&gt;AI làm giảm rào cản cho nội dung rác nhưng chưa đủ tốt để thay thế hoàn toàn công việc có ý nghĩa&lt;/li&gt;
&lt;li&gt;Các công ty AI dường như không quan tâm đến việc giải quyết các tác động tiêu cực như misinformation, gian lận trong giáo dục, và tăng giá phần cứng&lt;/li&gt;
&lt;li&gt;Tác giả đề xuất các giải pháp như watermarking, chặn misinformation, và bảo vệ các dự án open-source khỏi AI quét lỗ hổng&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="uber"&gt;&lt;a class="link" href="https://www.uber.com/en-IN/blog/ubers-rate-limiting-system/" target="_blank" rel="noopener"
&gt;Uber&amp;rsquo;s Rate Limiting System&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết chi tiết về cách Uber xây dựng hệ thống rate limiting phân tán quy mô lớn có khả năng xử lý hàng trăm triệu yêu cầu mỗi giây qua hàng nghìn dịch vụ microservices. Trước khi có GRL (Global Rate Limiter), các team tại Uber triển khai rate limiting theo cách riêng lẻ, dẫn đến cấu hình không nhất quán, độ trễ cao từ Redis, và khó khăn trong vận hành. Uber đã giải quyết vấn đề bằng cách tích hợp rate limiting trực tiếp vào service mesh.&lt;/p&gt;
&lt;p&gt;Hệ thống GRL sử dụng kiến trúc ba tầng với các client trong service mesh data plane, các aggregator cấp zone, và các controller cấp vùng. Thay vì sử dụng bộ đếm tập trung, GRL áp dụng mô hình probabilistic dropping được điều khiển bởi control plane — các client quyết định địa phương có nên drop request hay không dựa trên các chỉ thị drop ratio từ control plane. Thiết kế này cho phép decisions cực nhanh với độ trễ thấp trong khi vẫn duy trì coordination toàn cầu trong vài giây.&lt;/p&gt;
&lt;p&gt;Uber cũng xây dựng RLC (Rate Limit Configurator) để tự động hóa việc cấu hình rate limit. RLC phân tích định kỳ metrics traffic trực tiếp và cập nhật cấu hình rate limit dựa trên nhu cầu quan sát được, đảm bảo limits luôn mới và chính xác. Kết quả là giảm độ trễ median khoảng 1ms, giảm độ trễ P90 hàng chục ms, và cải thiện độ trễ đuôi (P99.5) lên đến 90%. GRL hiện xử lý khoảng 80 triệu yêu cầu mỗi giây trên hơn 1,100 dịch vụ.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GRL sử dụng kiến trúc phân tán ba tầng với probabilistic dropping để đạt độ trễ thấp và coordination toàn cầu&lt;/li&gt;
&lt;li&gt;Hệ thống loại bỏ dependency Redis, giảm độ trễ median 1ms và cải thiện độ trễ đuôi lên đến 90%&lt;/li&gt;
&lt;li&gt;RLC tự động hóa cấu hình rate limit bằng cách phân tích traffic trực tiếp và cập nhật limits dựa trên nhu cầu thực tế&lt;/li&gt;
&lt;li&gt;GRL xử lý 80 triệu RPS trên hơn 1,100 dịch vụ và đã ngăn chặn thành công các sự cố quá tải và tấn công DDoS&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="agents-feb-2026"&gt;&lt;a class="link" href="https://calv.info/agents-feb-2026" target="_blank" rel="noopener"
&gt;Agents (Feb 2026)&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết chia sẻ kinh nghiệm thực tế của tác giả về việc sử dụng các coding agent khác nhau bao gồm Claude Code (Opus) và Codex (GPT-5.3). Tác giả, người từng tham gia phát triển Codex web product, đã đi đến kết luận rằng cả hai mô hình đều có điểm mạnh và điểm yếu riêng liên quan đến cách đào tạo của chúng. Sự thay đổi lớn nhất trong workflow của ông là thời gian của ông giờ đây trở thành yếu tố quan trọng nhất — ông chọn coding agent dựa trên thời gian có sẵn và mức độ tự chủ mong muốn.&lt;/p&gt;
&lt;p&gt;Tác giả giải thích các nguyên tắc hướng dẫn khi sử dụng coding agents. Điều quan trọng nhất là phải hiểu context — các agent thực sự đang làm next token prediction và mỗi token phải nằm trong context window. Điều này dẫn đến nhiều hệ quả: công việc cần được chia nhỏ, compaction là kỹ thuật có loss, nên externalize context vào filesystem, và nên ở trong &amp;ldquo;nửa thông minh&amp;rdquo; của context window. Hiệu năng của mô hình bị chi phối bởi cả hiệu năng thuần túy của mô hình và khả năng quản lý nhiều context window cũng như ủy quyền cho sub-agents.&lt;/p&gt;
&lt;p&gt;Opus xuất sắc trong việc làm việc across context windows một cách hiệu quả, sử dụng tools tốt hơn, và có tính cách &amp;ldquo;người&amp;rdquo; hơn. Opus thường xuyên spin up nhiều sub-agents song song, sử dụng tool Explore rất nhanh với Haiku, và được đào tạo tốt để sử dụng các tools trên laptop. Trong khi đó, Codex tỏa sáng ở độ chính xác của code — code của Codex có ít bugs hơn đáng kể so với Opus, mặc dù Codex chậm hơn vì không delegate tasks across context windows tốt như Opus.&lt;/p&gt;
&lt;p&gt;Tác giả chia sẻ nhiều kỹ thuật và workflows hữu ích bao gồm: sử dụng thư mục &lt;code&gt;plans/&lt;/code&gt; cho các kế hoạch được đánh số, leverage Cloudflare Durable Objects cho APIs, sử dụng worktrees song song, và quy trình Plan-Implement-Review. Ông cũng xây dựng nhiều skills để tự động hóa workflows như &lt;code&gt;/commit&lt;/code&gt;, &lt;code&gt;/worktree&lt;/code&gt;, &lt;code&gt;/implement&lt;/code&gt;, &lt;code&gt;/address-bugs&lt;/code&gt;, và &lt;code&gt;/pr-pass&lt;/code&gt;. Tương lai theo hướng có laptop hoặc cloud sandbox constantly churning on ideas trong background, và ngày càng nhiều, ideas, architecture, và project sequencing sẽ trở thành các yếu tố giới hạn.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Opus xuất sắc ở context management, tool use, và tính cách con người trong khi Codex có độ chính xác code cao hơn&lt;/li&gt;
&lt;li&gt;Hiểu context window là quan trọng — công việc cần được chia nhỏ và externalize context vào filesystem&lt;/li&gt;
&lt;li&gt;Skills cho phép tự động hóa workflows và split context windows hiệu quả&lt;/li&gt;
&lt;li&gt;Tương lai hướng tới việc agents chạy 24/7 với ideas, architecture, và project sequencing trở thành yếu tố giới hạn&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-software-industrial-revolution"&gt;&lt;a class="link" href="https://cannoneyed.com/essays/software-industrial-revolution" target="_blank" rel="noopener"
&gt;The Software Industrial Revolution&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết so sánh sự thay đổi hiện tại trong phát triển phần mềm với Cách mạng Công nghiệp lần đầu tiên. Tác giả lập luận rằng chúng ta đang ở bước ngoặt của &amp;ldquo;Cách mạng Công nghiệp Phần mềm&amp;rdquo; — nơi AI coding agents vừa &amp;ldquo;click&amp;rdquo; và bắt đầu hoạt động hiệu quả. Giống như Spinning Jenny năm 1764 đã song song hóa quy trình dệt, giảm giá cotton cloth 90%, AI coding agents đang tự động hóa sản xuất phần mềm và giảm chi phí sản xuất hàng cấp độ.&lt;/p&gt;
&lt;p&gt;Tác giả giải thích rằng phần mềm đã &amp;ldquo;ăn&amp;rdquo; thế giới — ngành công nghệ chiếm khoảng 35% của S&amp;amp;P 500 và gần 50% nếu bao gồm cả communications. Nhưng chi phí sản xuất phần mềm cực kỳ cao đòi hỏi các mô hình kinh doanh problem như VC-funded growth-at-all-costs và &amp;ldquo;enshittification&amp;rdquo; của Cory Doctorow. Sự dồi dào của phần mềm thông qua tự động hóa sẽ mở rộng không gian mô hình kinh doanh phần mềm sang nhiều dạng bền vững hơn.&lt;/p&gt;
&lt;p&gt;Tác giả sử dụng ví dụ về Epic — công ty nắm 42% thị trường bệnh viện acute care Mỹ với biên lợi nhuận 30% — để minh họa cách chi phí phần mềm cao tạo ra độc quyền và kìm hãm cạnh tranh. Khi phần mềm trở nên rẻ hơn thông qua tự động hóa, chúng ta sẽ thấy sự bùng nổ của phần mềm bespoke mới trên mọi ngành và ngách. Tác giả kết luận rằng mặc dù việc sản xuất code sẽ thay đổi căn bản, các kỹ năng cốt lõi của software engineering — modeling domains, quản lý complexity, và sự tương tác giữa phần mềm và thế giới thực — sẽ chỉ trở nên quan trọng hơn.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Điểm chính:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cách mạng Công nghiệp Phần mềm đang giảm chi phí sản xuất phần mềm hàng cấp độ, giống như Cách mạng Công nghiệp giảm chi phí vải&lt;/li&gt;
&lt;li&gt;Chi phí phần mềm cao tạo ra độc quyền và các mô hình kinh doanh problem như enshittification&lt;/li&gt;
&lt;li&gt;Sự dồi dào của phần mềm sẽ cho phép bất kỳ ai cũng có thể tạo ra công cụ kỹ thuật số mà họ cần&lt;/li&gt;
&lt;li&gt;Các kỹ năng cốt lõi của software engineering sẽ trở nên quan trọng hơn ngay cả khi viết code bằng tay trở nên ít liên quan hơn&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Bài viết đã được review và cập nhật bởi Claude Code với Opus 4.7 (1M context).&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Newsletter #6</title><link>https://miti99.com/post/2025/03/08/</link><pubDate>Sat, 08 Mar 2025 00:00:00 +0700</pubDate><guid>https://miti99.com/post/2025/03/08/</guid><description>&lt;i&gt;
Mừng ngày Quốc tế Phụ nữ 8/3, chúc tất cả các bạn nữ một ngày tốt lành, luôn vui tươi và hạnh phúc!
Con gái sinh ra là để yêu thương :&gt;
Chào mừng các bạn đến với Newsletter #6.
&lt;/i&gt;
&lt;h2 id="how-i-use-llms-as-a-staff-engineer"&gt;&lt;a class="link" href="https://www.seangoedecke.com/how-i-use-llms/" target="_blank" rel="noopener"
&gt;How I use LLMs as a staff engineer&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Sean Goedecke, một staff engineer tại GitHub, chia sẻ cách anh tận dụng LLM (Large Language Models) trong công việc hàng ngày. Anh nhấn mạnh rằng, thay vì viết code hoàn toàn, LLM hiệu quả nhất khi được dùng như một công cụ hỗ trợ.&lt;/p&gt;
&lt;p&gt;Cụ thể, anh dùng Copilot cho việc &amp;ldquo;autocomplete&amp;rdquo; code, đặc biệt hữu ích khi làm việc với các ngôn ngữ hoặc vùng kiến thức ít quen thuộc. Với các đoạn code &amp;ldquo;throwaway&amp;rdquo; (chỉ dùng một lần), anh thoải mái dùng LLM để tăng tốc độ. Anh cũng sử dụng LLM như một &amp;ldquo;tutor&amp;rdquo; để học các domain mới, đặt câu hỏi và kiểm tra kiến thức.&lt;/p&gt;
&lt;p&gt;Ngoài ra, LLM còn được dùng để &amp;ldquo;debug&amp;rdquo; ở bước cuối cùng khi đã cạn ý tưởng, hoặc để &amp;ldquo;proofread&amp;rdquo; các tài liệu kỹ thuật dài. Sean không dùng LLM để viết PR (Pull Request) hoàn chỉnh hoặc các tài liệu quan trọng như ADR (Architecture Decision Record).&lt;/p&gt;
&lt;p&gt;Tóm lại, theo Sean, LLM là công cụ giá trị nếu được sử dụng đúng cách, giúp tăng năng suất và học hỏi nhanh hơn, đặc biệt khi làm việc ngoài vùng &amp;ldquo;expertise&amp;rdquo;.&lt;/p&gt;
&lt;h2 id="software-development-topics-i"&gt;&lt;a class="link" href="https://chriskiehl.com/article/thoughts-after-10-years" target="_blank" rel="noopener"
&gt;Software development topics I&amp;rsquo;ve changed my mind on after 10 years in the industry&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Chris Kiehl là một lập trình viên phần mềm hiện đang làm việc tại Amazon. Anh đã viết cuốn sách &amp;ldquo;Lập trình hướng dữ liệu trong Java&amp;rdquo; và tạo ra Gooey, một công cụ chuyển đổi hầu hết các chương trình dòng lệnh Python thành ứng dụng GUI đầy đủ chức năng chỉ với một dòng code. Bốn năm trước, Kiehl đã đăng một danh sách các chủ đề về phát triển phần mềm mà anh đã thay đổi quan điểm sau khi làm việc trong ngành công nghiệp. Đây là một bản cập nhật về quan điểm của Kiehl - những điều anh đã thay đổi suy nghĩ, những ý kiến anh đã tiếp thu trong quá trình làm việc, và những điều anh vẫn giữ nguyên quan điểm.&lt;/p&gt;
&lt;h2 id="looking-under-the-lamppost-on-problem-solving"&gt;&lt;a class="link" href="https://edbatista.com/2025/01/looking-under-the-lamppost-on-problem-solving.html" target="_blank" rel="noopener"
&gt;Looking Under the Lamppost (On Problem-Solving)&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Ed Batista mở đầu bài viết bằng một câu chuyện ngụ ngôn quen thuộc: một người đàn ông tìm chìa khóa dưới cột đèn, dù biết đã đánh rơi ở chỗ tối hơn. Câu chuyện này là phép ẩn dụ cho cách chúng ta thường tiếp cận việc giải quyết vấn đề. Thay vì đối mặt với vấn đề cần giải quyết, chúng ta lại tập trung vào vấn đề muốn giải quyết.&lt;/p&gt;
&lt;p&gt;Tác giả chỉ ra một số lý do cho hành vi này: vấn đề thực sự có thể nằm ngoài vùng chuyên môn, tốn quá nhiều thời gian, hoặc thậm chí không có lời giải. Thay vì đối mặt với những khó khăn này, chúng ta chọn những vấn đề nhỏ, dễ giải quyết để cảm thấy &amp;ldquo;hiệu quả&amp;rdquo; hoặc để bảo vệ hình ảnh cá nhân.&lt;/p&gt;
&lt;p&gt;Tuy nhiên, việc này kìm hãm sự phát triển của chúng ta. Để mở rộng vùng an toàn, chúng ta cần bước ra khỏi nó. Sự dũng cảm không chỉ là tự tin vào khả năng thành công, mà còn là nhận thức rằng cái giá của việc không thử còn lớn hơn cái giá của thất bại.&lt;/p&gt;
&lt;p&gt;Thất bại không phải là điều đáng sợ, mà là cơ hội để học hỏi và loại trừ các khả năng. Vì vậy, đừng mãi tìm kiếm dưới ánh đèn, hãy dũng cảm đối mặt với bóng tối, nơi những giải pháp thực sự đang chờ đợi.&lt;/p&gt;
&lt;h2 id="sliding-window-log-rate-limiter-redis--java"&gt;&lt;a class="link" href="https://foojay.io/today/sliding-window-log-rate-limiter-redis-java/" target="_blank" rel="noopener"
&gt;Sliding Window Log Rate Limiter (Redis &amp;amp; Java)&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết này giới thiệu về Sliding Window Log Rate Limiter, một phương pháp chính xác để kiểm soát tốc độ xử lý request. Thay vì chia thời gian thành các khoảng cố định, phương pháp này ghi lại dấu thời gian của từng request, cho phép theo dõi request trong một khoảng thời gian trượt (rolling time period) như giây hoặc phút.&lt;/p&gt;
&lt;p&gt;Bài viết hướng dẫn cách triển khai Sliding Window Log sử dụng Redis và Java, tận dụng command &lt;code&gt;HEXPIRE&lt;/code&gt; mới của Redis 8 để thiết lập thời gian hết hạn cho các field cụ thể trong một hash. Mỗi request (nếu được phép) sẽ được ghi lại bằng timestamp trong Redis hash. Sau đó, đếm số lượng request trong khoảng thời gian cho phép bằng command &lt;code&gt;HLEN&lt;/code&gt;. Nếu vượt quá giới hạn, request mới sẽ bị từ chối.&lt;/p&gt;
&lt;p&gt;Tác giả cũng cung cấp code mẫu Java sử dụng thư viện Jedis để tương tác với Redis, cùng với các test case sử dụng Redis TestContainers, JUnit 5 và AssertJ để đảm bảo rate limiter hoạt động đúng như mong đợi trong nhiều tình huống khác nhau, như kiểm tra số lượng request trong giới hạn, vượt quá giới hạn, sau khi sliding window reset, và xử lý đồng thời nhiều client.&lt;/p&gt;
&lt;h2 id="project-loom-structured-concurrency--java"&gt;&lt;a class="link" href="https://foojay.io/today/project-loom-structured-concurrency-java/" target="_blank" rel="noopener"
&gt;Project Loom: Structured Concurrency – Java&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết giới thiệu về Structured Concurrency, một tính năng mới được giới thiệu trong Java 19 (incubator), Java 21 (preview) và Java 23 (preview) như là một phần của Project Loom. Structured Concurrency giúp đơn giản hóa việc lập trình concurrent bằng cách tạo ra trật tự và tính dễ đoán trong quản lý task.&lt;/p&gt;
&lt;p&gt;Structured Concurrency hoạt động bằng cách chia một task chính thành nhiều subtask đồng thời và task chính không thể hoàn thành cho đến khi các subtask này hoàn tất. API này bao gồm lớp StructuredTaskScope (trong java.util.concurrent), cho phép tạo các subtask bằng StructuredTaskScope::fork và đợi chúng hoàn thành bằng StructuredTaskScope::join.&lt;/p&gt;
&lt;p&gt;Bài viết cũng giới thiệu StructuredTaskScope.ShutdownOnSuccess (hủy các subtask khác khi một subtask thành công) và StructuredTaskScope.ShutdownOnFailure (hủy các subtask khác khi một subtask thất bại). Ngoài ra, có thể debug bằng lệnh jcmd.&lt;/p&gt;
&lt;p&gt;Lợi ích của Structured Concurrency bao gồm đơn giản hóa quản lý task, cải thiện khả năng xử lý lỗi, đảm bảo an toàn tài nguyên và tính dễ đoán. Tính năng này hứa hẹn mang lại các ứng dụng concurrent hiện đại, dễ bảo trì và hiệu quả hơn.&lt;/p&gt;
&lt;h2 id="taking-out-the-trash-in-java"&gt;&lt;a class="link" href="https://medium.com/@benweidig/taking-out-the-trash-in-java-19bcc0c7bd0c" target="_blank" rel="noopener"
&gt;Taking Out the Trash in Java&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết này cung cấp một cái nhìn tổng quan về Garbage Collection (GC) trong Java, một cơ chế quản lý bộ nhớ tự động quan trọng của JVM. Thay vì yêu cầu developer tự quản lý việc cấp phát và giải phóng bộ nhớ, GC tự động xác định và thu hồi bộ nhớ không còn được sử dụng, giúp giảm thiểu lỗi và đơn giản hóa quá trình phát triển.&lt;/p&gt;
&lt;p&gt;Bài viết giải thích cách JVM chia bộ nhớ thành các vùng khác nhau như Heap (nơi lưu trữ đối tượng) và Stack (nơi quản lý các lời gọi phương thức và biến cục bộ). Heap lại được chia thành Young Generation (Eden Space và Survivor Spaces) cho các đối tượng mới tạo và Old Generation cho các đối tượng tồn tại lâu hơn.&lt;/p&gt;
&lt;p&gt;Bài viết cũng giới thiệu các loại GC khác nhau có sẵn trong JVM, bao gồm Serial GC, Parallel GC, G1 GC, ZGC, Shenandoah GC và Epsilon GC. Mỗi loại GC có các thuật toán và ưu tiên khác nhau, được tối ưu hóa cho các khối lượng công việc khác nhau. Ví dụ: ZGC được thiết kế để có độ trễ cực thấp, trong khi Parallel GC tập trung vào thông lượng cao.&lt;/p&gt;
&lt;p&gt;Cuối cùng, bài viết cung cấp các mẹo thực tế để giảm thiểu garbage, gỡ lỗi và phân tích GC, cũng như điều chỉnh các cài đặt GC để cải thiện hiệu suất ứng dụng.&lt;/p&gt;
&lt;h2 id="how-precision-time-protocol-handles-leap-seconds"&gt;&lt;a class="link" href="https://engineering.fb.com/2025/02/03/production-engineering/how-precision-time-protocol-ptp-handles-leap-seconds/" target="_blank" rel="noopener"
&gt;How Precision Time Protocol handles leap seconds&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết này thảo luận về cách Facebook (Meta) xử lý leap seconds (giây nhuận) trong hệ thống của họ, đặc biệt là với sự gia tăng của Precision Time Protocol (PTP) cho đồng bộ hóa thời gian chính xác trong các trung tâm dữ liệu.&lt;/p&gt;
&lt;p&gt;Trước đây, Meta sử dụng &amp;ldquo;leap second smearing&amp;rdquo; cho NTP (Network Time Protocol), nhưng với PTP, phương pháp này không còn phù hợp do yêu cầu độ chính xác cao hơn (nanosecond). Leap second smearing là quá trình điều chỉnh tốc độ đồng hồ để bù đắp cho giây nhuận.&lt;/p&gt;
&lt;p&gt;Giải pháp của Meta cho PTP là &amp;ldquo;self-smearing&amp;rdquo; bằng thư viện fbclock, sử dụng thuật toán dịch thời gian tự động, stateless và reproducible. Tuy nhiên, phương pháp này vẫn tạo ra sự khác biệt đáng kể giữa các host trong quá trình smearing.&lt;/p&gt;
&lt;p&gt;Do đó, Meta khuyến nghị sử dụng TAI (International Atomic Time) thay vì UTC (Coordinated Universal Time) để tránh phải xử lý giây nhuận. Tuy nhiên, trong nhiều trường hợp, việc chuyển đổi sang UTC vẫn cần thiết.&lt;/p&gt;
&lt;p&gt;Cuối cùng, Meta ủng hộ việc ngừng thêm giây nhuận sau năm 2035 để toàn ngành có thể dựa vào UTC, đơn giản hóa cơ sở hạ tầng và loại bỏ các giải pháp smearing khác nhau. Một tương lai không có giây nhuận sẽ giúp hệ thống đạt được độ chính xác thời gian cao hơn một cách dễ dàng và hiệu quả.&lt;/p&gt;
&lt;h2 id="developer-philosophy"&gt;&lt;a class="link" href="https://qntm.org/devphilo" target="_blank" rel="noopener"
&gt;Developer philosophy&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết này trình bày triết lý phát triển phần mềm của qntm, một nhà văn khoa học viễn tưởng và nhà phát triển phần mềm. Trong một buổi thảo luận với các nhà phát triển mới, qntm đã chia sẻ bảy nguyên tắc cốt lõi trong triết lý phát triển của mình:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tránh việc viết lại từ đầu&lt;/strong&gt;: Nếu việc viết lại toàn bộ dự án trở nên hấp dẫn, điều đó cho thấy đã có những sai lầm không thể tránh khỏi. Hãy theo dõi các dấu hiệu như nợ kỹ thuật tăng, khó khăn khi thay đổi code, và khó khăn khi ghi chú hoặc giới thiệu cho các nhà phát triển mới.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Hoàn thành 90% công việc trong 50% thời gian&lt;/strong&gt;: Nhiều dự án mất 90% thời gian cho 90% công việc đầu tiên và 90% thời gian còn lại cho 10% cuối cùng. Hãy sử dụng thời gian còn lại để cải thiện quy trình hoặc trả nợ kỹ thuật.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tự động hóa các thói quen tốt&lt;/strong&gt;: Thay vì nhắc nhở mọi người thực hiện các hành vi tốt một cách thủ công, hãy tự động hóa chúng bằng cách thêm các kiểm tra tự động hoặc sửa lỗi tự động.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tư duy về dữ liệu bệnh lý&lt;/strong&gt;: Thay vì chỉ tập trung vào trường hợp lý tưởng, hãy nghĩ về cách mọi thứ có thể thất bại và viết code để xử lý các trường hợp đó.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Luôn tìm cách viết code tốt hơn&lt;/strong&gt;: Nếu có thời gian, hãy xem xét lại code để tìm cách cải thiện.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Viết code có thể kiểm thử&lt;/strong&gt;: Code nên có giao diện rõ ràng và ít tác dụng phụ để dễ dàng kiểm thử.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Code không chỉ đúng mà còn phải rõ ràng và dễ hiểu&lt;/strong&gt;: Tránh code hoạt động &amp;ldquo;tình cờ&amp;rdquo; mà không có lý do rõ ràng. Code nên rõ ràng, dễ nhìn và dễ hiểu ngay cả khi không có lỗi.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Bài viết này cung cấp một cái nhìn sâu sắc về cách tiếp cận phát triển phần mềm một cách hiệu quả và bền vững&lt;/p&gt;
&lt;h2 id="bonus"&gt;Bonus
&lt;/h2&gt;&lt;h3 id="bonus-1-vài-video-hay-ho-đến-từ-bytebytego"&gt;Bonus 1: Vài video hay ho đến từ &lt;a class="link" href="https://bytebytego.com/" target="_blank" rel="noopener"
&gt;ByteByteGo&lt;/a&gt;
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://www.youtube.com/watch?v=QEzbZKtLi-g" target="_blank" rel="noopener"
&gt;System Design: Why Is Docker Important?&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="bonus-2-vài-ảnh-hay-ho-đến-từ-bytebytego"&gt;Bonus 2: Vài ảnh hay ho đến từ &lt;a class="link" href="https://bytebytego.com/" target="_blank" rel="noopener"
&gt;ByteByteGo&lt;/a&gt;
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://substack-post-media.s3.amazonaws.com/public/images/fc4c9cac-3046-4b45-9dd8-7dccc79b4e2c_1280x1608.gif"
loading="lazy"
alt="JWT 101: Key to Stateless Authentication"
&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Bài viết đã được review và cập nhật bởi Claude Code với Opus 4.7 (1M context).&lt;/em&gt;&lt;/p&gt;</description></item><item><title>Newsletter #2</title><link>https://miti99.com/post/2025/02/16/</link><pubDate>Sun, 16 Feb 2025 00:00:00 +0700</pubDate><guid>https://miti99.com/post/2025/02/16/</guid><description>&lt;i&gt;
Chào các bạn, đến hẹn lại lên, đây là Newsletter #2 của mình. Cuối tuần này mình đi chơi ở Xuyên Mộc, vừa về hôm nay thôi nên giờ mới lên bài.
&lt;p&gt;Thôi không vòng vo nữa, vào ngay Newsletter #2 của MiTi nào.
&lt;/i&gt;&lt;/p&gt;
&lt;h2 id="some-things-to-expect-in-2025"&gt;&lt;a class="link" href="https://lwn.net/Articles/1003780/" target="_blank" rel="noopener"
&gt;Some things to expect in 2025&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết dự đoán một số xu hướng và sự kiện có thể xảy ra trong cộng đồng Linux và phần mềm tự do năm 2025. Đầu tiên, sched-ext sẽ trở thành yếu tố thay đổi cuộc chơi, cho phép tải trình lập lịch CPU từ không gian người dùng thông qua BPF, thúc đẩy sự sáng tạo và thử nghiệm. Mã Rust sẽ được tích hợp nhiều hơn vào kernel, mang lại các tính năng mà người dùng cuối có thể không nhận ra. Bài viết cảnh báo về một nỗ lực backdoor tương tự như XZ có thể xuất hiện, và các dự án chỉ có một người duy trì sẽ bị coi là rủi ro hơn.&lt;/p&gt;
&lt;p&gt;Một dự án lớn có thể phát hiện ra rằng họ đã hợp nhất nhiều mã do AI tạo ra mà tác giả không thực sự hiểu. Đồng thời, sẽ có nhiều nỗ lực tập trung hơn vào việc tạo ra các hệ thống AI tạo sinh thực sự tự do. Các tổ chức hỗ trợ công việc phần mềm tự do sẽ tiếp tục gặp khó khăn. Nhiều sản phẩm dựa trên đám mây sẽ trở thành &amp;ldquo;cục gạch&amp;rdquo; khi nhà sản xuất phá sản hoặc ngừng hỗ trợ. Phần cứng hoàn toàn mở sẽ trở nên phổ biến hơn, và các bản phân phối cho thiết bị di động sẽ chứng kiến sự quan tâm trở lại. Cuối cùng, bài viết nhấn mạnh rằng sự hiếu chiến toàn cầu sẽ tác động đến cộng đồng, và lời kêu gọi được đưa ra là hãy giữ vững các giá trị cốt lõi của cộng đồng trong bối cảnh chính trị phân cực.&lt;/p&gt;
&lt;h2 id="why-you-should-use-compact-table-columns"&gt;&lt;a class="link" href="https://vladmihalcea.com/compact-table-columns/" target="_blank" rel="noopener"
&gt;Why you should use compact table columns&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết giải thích tầm quan trọng của việc sử dụng các kiểu cột (column types) nhỏ gọn trong thiết kế cơ sở dữ liệu để tăng tốc độ truy vấn SQL. Việc sử dụng các kiểu cột nhỏ gọn cho phép lưu trữ nhiều bản ghi và mục chỉ mục hơn trong bộ nhớ cache, giúp giảm thiểu số lần truy cập đĩa. StackOverflow là một ví dụ điển hình, họ đã sử dụng chiến lược này để phục vụ hàng nghìn truy vấn mỗi giây chỉ với một máy chủ SQL duy nhất.&lt;/p&gt;
&lt;p&gt;Bài viết chỉ ra rằng việc sử dụng các khóa chính (Primary Key) và khóa ngoại (Foreign Key) kiểu int hoặc tinyint thay vì UUID hoặc bigint, biểu diễn giá trị enum bằng 1 byte, và giới hạn độ dài của các cột VARCHAR giúp tiết kiệm không gian lưu trữ. Tác giả cũng trình bày các ví dụ cụ thể trên MySQL và PostgreSQL, cho thấy việc sử dụng các kiểu cột nhỏ gọn có thể giảm đáng kể kích thước bảng và chỉ mục, từ đó cải thiện hiệu suất truy vấn. Tuy nhiên, cần lưu ý về việc căn chỉnh cột (column alignment) trong PostgreSQL để đạt hiệu quả tối ưu. Tóm lại, việc lựa chọn kiểu cột phù hợp là một yếu tố quan trọng để tối ưu hóa hiệu suất cơ sở dữ liệu.&lt;/p&gt;
&lt;h2 id="rate-limiting-with-redis-an-essential-guide"&gt;&lt;a class="link" href="https://foojay.io/today/rate-limiting-with-redis-an-essential-guide/" target="_blank" rel="noopener"
&gt;Rate limiting with Redis: An essential guide&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết này giới thiệu về rate limiting (giới hạn tốc độ truy cập), giải thích tầm quan trọng của nó trong việc bảo vệ tài nguyên khỏi bị quá tải, ngăn chặn lạm dụng, đảm bảo truy cập công bằng, quản lý tải, giảm chi phí và bảo vệ hệ thống khỏi downtime. Redis được giới thiệu như một công cụ phổ biến để triển khai rate limiter nhờ tốc độ, độ tin cậy và các tính năng như thao tác nguyên tử, lưu trữ dữ liệu và Lua scripting.&lt;/p&gt;
&lt;p&gt;Bài viết trình bày chi tiết các thuật toán rate limiting phổ biến: Leaky Bucket (ổn định luồng traffic), Token Bucket (xử lý các đợt tăng đột biến), Fixed Window Counter (đơn giản, độ chính xác thấp), Sliding Window Log (độ chính xác cao, tốn nhiều tài nguyên) và Sliding Window Counter (cân bằng giữa độ chính xác và hiệu quả).&lt;/p&gt;
&lt;p&gt;Để chọn thuật toán phù hợp, cần hiểu rõ đặc điểm traffic (dự đoán được, đột biến, hỗn hợp), mức độ chính xác cần thiết, giới hạn tài nguyên (bộ nhớ, CPU, khả năng mở rộng) và trải nghiệm người dùng. Bài viết nhấn mạnh rằng rate limiting không chỉ là việc thiết lập giới hạn mà còn là thiết kế các hệ thống hiệu quả, công bằng và thân thiện với người dùng. Các triển khai cho từng loại rate limiter với Java &amp;amp; Redis sẽ được phát hành hàng tuần.&lt;/p&gt;
&lt;h2 id="why-does-cloudflare-pages-have-such-a-generous-free-tier"&gt;&lt;a class="link" href="https://mattsayar.com/why-does-cloudflare-pages-have-such-a-generous-free-tier/" target="_blank" rel="noopener"
&gt;Why does Cloudflare Pages have such a generous Free tier?&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết của Matt Sayar khám phá lý do tại sao Cloudflare Pages lại có một gói miễn phí hào phóng trong bối cảnh nhiều dịch vụ hosting hiện nay cung cấp các gói miễn phí tương tự. Cloudflare Pages nổi bật với băng thông không giới hạn, điều mà ít nền tảng nào khác có thể cạnh tranh. Các dịch vụ như GitHub Pages, GitLab Pages và Netlify đều có giới hạn băng thông, trong khi Cloudflare cho phép người dùng thoải mái phát triển trang web mà không lo lắng về chi phí phát sinh.&lt;/p&gt;
&lt;p&gt;Tác giả cho rằng việc cung cấp băng thông không giới hạn phù hợp với chiến lược của Cloudflare trong việc phát triển một internet an toàn và nhanh chóng. Một trang web tĩnh nhẹ nhàng và dễ phục vụ, giúp Cloudflare tiết kiệm chi phí. Hơn nữa, khi người dùng trải nghiệm dịch vụ miễn phí, họ có xu hướng có ấn tượng tích cực và có thể chuyển sang sử dụng các sản phẩm trả phí của Cloudflare trong tương lai.&lt;/p&gt;
&lt;p&gt;Bài viết cũng nhấn mạnh rằng Cloudflare đang đầu tư vào việc cải thiện internet và cung cấp nhiều dịch vụ bảo mật miễn phí, từ đó tạo ra một vòng luân chuyển lợi ích cho cả người dùng và công ty. Tác giả kết luận rằng đây là một cơ hội tốt để thử nghiệm các sản phẩm mới của Cloudflare, đặc biệt là trong thời gian gói miễn phí vẫn còn hiệu lực.&lt;/p&gt;
&lt;h2 id="how-i-program-with-llms"&gt;&lt;a class="link" href="https://crawshaw.io/blog/programming-with-llms" target="_blank" rel="noopener"
&gt;How I program with LLMs&lt;/a&gt;
&lt;/h2&gt;&lt;p&gt;Bài viết này tổng hợp những kinh nghiệm cá nhân của tác giả trong việc sử dụng các mô hình ngôn ngữ lớn (LLM) trong lập trình trong năm vừa qua. Tác giả nhấn mạnh rằng việc sử dụng LLM đã mang lại hiệu quả tích cực cho năng suất làm việc, và việc quay trở lại lập trình mà không có chúng trở nên khó khăn. Tác giả thường sử dụng LLM để tự động hóa các bước lặp đi lặp lại và một công cụ có tên sketch.dev đang được phát triển để hỗ trợ lập trình Go.&lt;/p&gt;
&lt;p&gt;Có ba cách chính mà tác giả sử dụng LLM: để tự động hoàn thành code, cho các tác vụ tìm kiếm, và trong các phiên lập trình dựa trên chat. Tác giả thấy rằng LLM đặc biệt hữu ích khi anh ta biết những gì cần viết, nhưng không có đủ năng lượng để bắt đầu một file mới, tra cứu các thư viện cần thiết. LLM cung cấp bản nháp đầu tiên, thường chứa các ý tưởng hay, các dependency cần thiết và một vài lỗi. Việc sửa các lỗi này thường dễ dàng hơn là bắt đầu từ đầu.&lt;/p&gt;
&lt;p&gt;LLM cũng rất hữu ích trong việc tạo ra các code review packet, đặc biệt là khi chúng cần sử dụng nhiều thư viện phổ biến. Tuy nhiên, cần phải biên dịch và chạy thử code do LLM tạo ra trước khi đọc kỹ, vì chúng có thể tạo ra code không biên dịch được.&lt;/p&gt;
&lt;p&gt;Ví dụ, tác giả đã sử dụng LLM để viết một reservoir sampler cho các quartiles của các số float. LLM đã tạo ra một package có cấu trúc tốt, interface tốt và các test, nhưng code ban đầu không biên dịch được và các test chứa các giá trị sai. Tác giả đã sửa các lỗi này và sau đó yêu cầu LLM tạo ra các test tốt hơn bằng cách so sánh kết quả của reservoir sampler với một triển khai tiêu chuẩn. LLM đã tạo ra một fuzz test, nhưng nó chứa một lỗi cú pháp. Sau khi tác giả sửa lỗi này, fuzz test đã hoạt động tốt.&lt;/p&gt;
&lt;p&gt;Nhìn chung, tác giả kết luận rằng LLM có thể là một công cụ hữu ích cho các lập trình viên, nhưng chúng không hoàn hảo và cần được sử dụng một cách cẩn thận. LLM có thể giúp cải thiện năng suất, viết test toàn diện hơn và làm cho code dễ đọc hơn.&lt;/p&gt;
&lt;h2 id="bonus"&gt;Bonus
&lt;/h2&gt;&lt;p&gt;Tuần này có kha khá bonus đến từ nhiều nguồn khác nhau&lt;/p&gt;
&lt;h3 id="bonus-1-một-vài-ebook-mình-tìm-được"&gt;Bonus #1: Một vài ebook mình tìm được
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://info.microsoft.com/rs/157-GQE-382/images/EN-CNTNT-eBook-DesigningDistributedSystems.pdf" target="_blank" rel="noopener"
&gt;Designing Distributed Systems&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://drive.google.com/file/d/1U7EchvgzCjTtF5JzGVVCFgjXC-qw7lIG/view" target="_blank" rel="noopener"
&gt;Quastor Summaries&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="bonus-2-vài-ảnh-hay-ho-đến-từ-bytebytego"&gt;Bonus #2: Vài ảnh hay ho đến từ &lt;a class="link" href="https://bytebytego.com/" target="_blank" rel="noopener"
&gt;ByteByteGo&lt;/a&gt;
&lt;/h3&gt;&lt;p&gt;&lt;img src="https://substack-post-media.s3.amazonaws.com/public/images/11b53f30-8dba-4520-9b1a-425b54b9b84a_1280x1585.gif"
loading="lazy"
alt="Cookies Vs Sessions Vs JWT Vs PASETO"
&gt;
&lt;img src="https://substack-post-media.s3.amazonaws.com/public/images/fdbcc119-8f5d-4d27-9a4b-2c8bde82b537_4026x8030.jpeg"
loading="lazy"
alt="Algorithms you should know before taking System Design Interviews"
&gt;
&lt;img src="https://substack-post-media.s3.amazonaws.com/public/images/12dffcce-f231-48cc-915f-d53c0f8bce0c_3735x3573.jpeg"
loading="lazy"
alt="Top 6 Load Balancing Algorithms"
&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Bài viết đã được review và cập nhật bởi Claude Code với Opus 4.7 (1M context).&lt;/em&gt;&lt;/p&gt;</description></item></channel></rss>