AI 资讯
HLD Fundamentals #4: How Systems Scale: From 0 to 100 Million Users
One of the most common system design interview questions is: "How would you scale a web application from 100 users to 100 million users?" The answer is rarely a single technology. Instead, systems evolve through multiple stages, with each stage solving a specific bottleneck. This article walks through the typical evolution of a scalable system and explains why , how , and when each component is introduced. 1. Single Server Why Start Here? Every application starts simple. In the beginning: Traffic is low Development speed matters more than scalability Infrastructure costs should be minimal What Is It? A single machine handles everything: Frontend Backend Database Users | v Single Server ├── Application └── Database How Does It Work? User sends request. Application processes request. Database stores and retrieves data. Response is returned. Everything happens on one machine. Problem As traffic grows: CPU becomes overloaded Memory becomes insufficient Database competes with application for resources A single server becomes a bottleneck. Interview One-Liner A single server architecture is simple and cost-effective but becomes a bottleneck as traffic and resource usage increase. 2. Application and Database Separation Why Do We Need It? The application and database have different workloads. Application Server: Uses CPU Handles business logic Database Server: Uses memory and storage Handles queries Keeping them together causes resource contention. How Does It Work? Move the database to a separate machine. Users | v Application Server | v Database Server Benefits Independent scaling Better resource utilization Improved performance Example Suppose an e-commerce website receives thousands of requests. The application handles: Authentication Order processing API responses The database handles: Product data Orders User information Separating them prevents one workload from affecting the other. Interview One-Liner Separating the application and database allows each layer to scal
AI 资讯
Cache Stale Data Issues
Originally published on lavkesh.com I recall one of the first design decisions for our payments platform, which was to deploy an in-memory cache for low-latency access to customer account balances. The architecture diagrams looked clean, with Go services using sync.Once-initialized maps in memory, bypassing the database for sub-millisecond reads. However, this approach worked as expected for only three months, until users started reporting inconsistent charges on receipts. The problem surfaced at peak hours when concurrent updates to the same balance would overwrite each other. For instance, the account balance for user ID 12345 went from $1,200 to $850 to $1,200 again within seconds, leaving the cache in a state that defied the database of record. Engineers stared at the logs, baffled by the mismatch between transactions and cached values, because the team had not accounted for the fact that memory maps are not thread-safe by default in Go. Debugging revealed the fundamental error: we were optimizing for speed without considering write-through guarantees. The cache treated concurrent requests as idempotent, which they were not. During a single user’s purchase flow, multiple goroutines could validate the balance, each reading a stale value from memory before any had a chance to commit updates. We had to shift to Redis with explicit lock keys and time-to-live settings, adding 4 milliseconds of latency but ensuring atomicity. The cache also invalidated itself only when a change occurred, not when an upstream source updated. We discovered this when the accounting team reconciled overnight and adjusted balances based on fee settlements - the cache never reflected these updates until it expired naturally. To fix this, we had to implement message queues to broadcast invalidation events across all services. What started as a performance optimization became three nights’ worth of rewriting concurrency models. This experience taught me two concrete lessons about distributed
AI 资讯
Codewars did not teach me JavaScript. My job did.
Why your brain learns faster by doing than by studying, and the neuroscience that explains...
AI 资讯
HLD Fundamentals #3: Microservices Design Patterns: Strangler, Saga, and CQRS
When organizations scale, a simple monolithic architecture often becomes difficult to maintain, deploy, and scale. This is where microservices come into the picture. However, moving to microservices introduces new challenges: How do we migrate from a monolith safely? How do we handle transactions across multiple services? How do we scale read-heavy applications efficiently? Three popular patterns solve these problems: Strangler Pattern – Monolith to Microservices Migration Saga Pattern – Distributed Transaction Management CQRS (Command Query Responsibility Segregation) – Read/Write Scalability 1. Strangler Pattern Why Do We Need It? Most companies cannot shut down a production monolith and rewrite everything from scratch. A complete rewrite is risky because: Development takes a long time. Existing customers are affected. Bugs can impact business operations. Rollback becomes difficult. The Strangler Pattern allows teams to migrate gradually with minimal risk. What Is It? The Strangler Pattern is a migration strategy where new microservices slowly replace parts of a monolithic application until the monolith is no longer needed. The name comes from the strangler fig tree, which gradually grows around another tree and eventually replaces it. How Does It Work? [Insert diagram here showing Client → API Gateway → Monolith + Microservices] Step 1 All requests go to the monolith. Client | v Monolith Step 2 Introduce an API Gateway (or Controller). Client | v API Gateway | v Monolith Step 3 Extract one module into a microservice. Client | v API Gateway |------> Order Service | v Monolith Step 4 Gradually move more modules. Client | v API Gateway |------> Order Service |------> Payment Service |------> Inventory Service | v Monolith Step 5 Eventually remove the monolith completely. Example Consider an e-commerce application. Initially, everything exists inside one application: Monolith ├── Orders ├── Payments ├── Inventory └── Users Over time: Orders become Order Service Payme
AI 资讯
NeMo out, GGUF in: how parakeet.cpp ports NVIDIA ASR to C++
NVIDIA's Parakeet speech models used to mean a Python stack: NeMo, PyTorch, and a GPU you kept warm. A new C++ port collapses that to one binary and one file. From NeMo to GGUF: What the Port Covers parakeet.cpp is a C++17 inference port that runs NVIDIA's Parakeet automatic speech recognition (ASR) models on the ggml tensor library — the same engine behind whisper.cpp and llama.cpp — with no Python, no NeMo, and no ONNX at inference time. The project is maintained by Ettore Di Giacinto (@mudler), author of LocalAI, and its first tagged release, v0.1.0, landed on May 30, 2026 . The code is MIT-licensed; the model weights keep their original NVIDIA Parakeet licenses. This is a community project, not an official NVIDIA release. The port covers the offline Parakeet families — CTC, RNNT, TDT and hybrid TDT-CTC — in 110M, 0.6B and 1.1B sizes, plus a streaming 120M model with end-of-utterance detection . Two checkpoints anchor most use: parakeet-tdt-0.6b-v2 , the English default that reports 6.05% average WER on the Hugging Face Open ASR Leaderboard and was released 05/01/2025 , and parakeet-tdt-0.6b-v3 , which extends the same 600M FastConformer-TDT architecture to 25 European languages with automatic language detection, released 08/14/2025 . Inference runs on CPU, CUDA, HIP (AMD ROCm), Vulkan and Metal (Apple Silicon) — the same ggml backend matrix as whisper.cpp and llama.cpp — so deployment reduces to one binary plus one GGUF file . The hard part was mapping Parakeet's RNNT/TDT decoders onto a static-graph tensor library. An earlier work-in-progress port surfaced on Hacker News in mid-2025, where the author flagged how far there was to go: "The GGML build is roughly 1000x slower than the MLX Python version" — jason-ni, reporting an early Parakeet-on-ggml experiment (source: Hacker News, 2025 ; see also the jason-ni port ). The mudler release is the matured answer to that decoder-on-static-graph problem, and as of June 2026 Parakeet is not yet merged into mainline whis
AI 资讯
My Polymarket Trading Bot in Rust After TypeScript Kept Missing Fills
A trader I was talking to recently said something that stuck with me: "I've blown accounts just from slow fills or missed order cancellations." He was talking about CEX perpetuals. But the problem is identical on Polymarket's CLOB - just measured in seconds instead of milliseconds. My TypeScript bot was averaging 340ms from signal detection to order placement on Polymarket's Central Limit Order Book. On a 5-minute market with a ~2.7-second mispricing window, that's 12% of the entire opportunity window consumed before a single byte hits Polymarket's servers. I was consistently entering at 74¢ when I'd detected the signal at 70¢. The market had already repriced against me. So I rewrote it in Rust. This article documents exactly what I found, what changed, and - critically - what didn't. Background: What My Bot Was Doing If you've read my earlier posts in this series ( architecture , Kelly Criterion sizing , last-60-seconds capture ), you know the context. But the short version: The bot targets Polymarket's 5-minute and 15-minute crypto up/down binary markets (BTC, ETH, XRP, SOL, DOGE, BNB). The strategy is simple: find markets that are briefly mispriced relative to real-time spot momentum, enter at a discount to fair value, hold to resolution. A 5-minute "XRP Up" market priced at 70¢ when spot momentum suggests 82% probability = +12¢ edge per dollar wagered. Do that 50 times a day with disciplined sizing and the math works - if you can actually get filled at the price you detected. The problem: by the time my TypeScript code detected the signal, formatted the order, opened an HTTP connection to Polymarket's CLOB API, waited for TLS handshake, serialized the payload, and received confirmation, the market had often moved to 74-76¢. I was paying for an edge I wasn't capturing. Profiling the TypeScript Bot: Where Was the 340ms Going? Before rewriting anything, I instrumented every stage of the order path. Here's what I found across 500 sampled trades: Stage Average time %
科技前沿
The UK Will Scan Asylum-Seekers’ Faces for Age Checks—Despite Knowing the Tech Is Flawed
Internal Home Office tests of age-verification technology show the risks of life-altering errors. It’s moving forward anyway.
科技前沿
Vitamix Promo Codes and Deals: $25 Off + Free Shipping
Score discounts on blenders, food processors, immersion blenders, and more with our selection of Vitamix coupons and deals.
AI 资讯
Where's the line between aggressive marketing and crossing it?
We're building an AI marketing operation in public, and early on we hit a question we couldn't skip: how aggressive can you be about growth before you've crossed into something you'll regret? "Be ethical" is easy to say and useless under pressure. Every real decision is messier than that. Is using a VPN cheating? Is running more than one channel a trick? Is bending a platform's rules the same as lying? We needed a line we could actually hold at 2am when a shortcut looks tempting. Here's the one we found — and it turned out to be simpler and sturdier than "follow all the rules." The line isn't rule-breaking. It's deception. The cleanest test we landed on: the line is deception, not rule-breaking. Breaking a rule is a fight you can have in the open. You can announce it, defend it, and accept what comes. Deception is different — it works by making someone believe something false, which strips away their ability to respond honestly, because they don't even know what's real. That's the move that does the damage. So the question to ask about any tactic isn't "did this break a rule?" It's: "does this work by causing a real person to believe something that isn't true?" If yes, that's the line. If no, you're probably fine even if you're being bold. The daylight test Here's how to apply it fast. Ask: would this tactic still work if everyone could see exactly what I was doing? If yes — it survives daylight. People are choosing freely with full information. That's honest, even when it's aggressive. If it only works in the dark — the concealment itself has become the product. Something only works hidden because someone is acting on a false belief you planted. That's the part to cut. A poker bluff survives daylight (everyone knows bluffing is part of poker). A magician's trick survives daylight (the audience knows it's a trick and enjoys it). A fake testimonial does not. A sock-puppet account vouching for you does not. Run every growth idea through the daylight test and most hard
AI 资讯
I published a rule for picking AI tools. A commenter rewrote it into a better one.
A couple of weeks ago I published a post with a tidy rule in it. When you add capability to an AI coding agent, reach for the lightest option first: a procedure file before a CLI, a CLI before a heavier integration, and only build the heavy machinery once you've proven you'll reuse it. My whole case rested on context cost. The heavy options load a lot of definitions up front and carry them every turn, so starting light keeps the window clean. I still think the front half is right. But it isn't the rule I'd write now, because a reader took it apart in the comments and handed it back as something better. This post is about that exchange, because the rewrite was sharper than my original, and pretending I arrived at it alone would be both a lie and the less interesting story. The hole, found in one comment The first comment didn't argue with the rule. It walked straight to the blind spot. The moment a tool touches anything external or stateful, lightest-first reverses on you: a lightweight call that fails silently halfway through is harder to debug than a heavier tool that surfaces the failure cleanly. Pay the complexity up front. My first instinct was to defend, and I did, a little. I said we were measuring different things, that I'd optimized for context cost while they were optimizing for failure observability, both real, different axes. I held the line by pointing out you can wrap a lightweight call to fail loudly, so the cheap path stays open. That was true, and it was beside their point, and they didn't let me hide behind it. The question that moved the rule They asked one question that did more work than my entire post: what's your actual trigger for paying the complexity up front, the type of state, or the class of error? Sitting with that is where my own rule changed under me. The honest answer is state type, and the moment I said it out loud, context cost stopped being what the rule was about. What makes a failure expensive isn't the error. It's whether the op
AI 资讯
[System Design] Part 4 — Amazon CONDOR & Anticipatory Shipping
Amazon Fulfillment: The Three Tiers of Optimization Amazon processes billions of orders annually through a network of over 175 fulfillment centers globally. To maintain their 1-2 day (or same-day) delivery guarantees, they built a 3-tier optimization architecture: ┌─────────────────────────────────────────────────────────────┐ │ TIER 1: ANTICIPATORY SHIPPING (Long-term — weeks/months) │ │ → ML predicts demand → Moves inventory close to customers │ │ BEFORE they place an order │ ├─────────────────────────────────────────────────────────────┤ │ TIER 2: REGIONALIZATION (Medium-term — days/weeks) │ │ → Partitions the fulfillment network into autonomous zones│ │ → Ensures 70-80% of orders are fulfilled intra-region │ ├─────────────────────────────────────────────────────────────┤ │ TIER 3: CONDOR (Short-term — hours) │ │ → Continuously re-optimizes the fulfillment plan within │ │ a 5-6 hour window before pick-and-pack begins. │ └─────────────────────────────────────────────────────────────┘ Anticipatory Shipping — Shipping Before You Buy A Crazy but Effective Idea Amazon holds a patent (US Patent 8,615,473) describing a system that begins shipping items BEFORE a customer places an order . It sounds like science fiction, but it's a reality. Traditional Model: Customer orders → Warehouse processes → Ships → Delivered (2-5 days) Anticipatory Shipping: ML predicts: "Customers in Region X will buy 200 iPhone 16s in the next 3 days" → Amazon ships 200 iPhones from a central hub to local delivery hubs in Region X → Customer places order → The item is already locally staged → Delivered same-day! ML Model Input Features Input Feature Significance Purchase history What do they buy, and how often? Browsing behavior What are they looking at? Cart abandonment? Wishlists Explicitly desired items Seasonal patterns Winter coats in November, sunscreen in June Regional demographics High-income areas? Young families? College towns? Trending products Items going viral on social media Weathe
AI 资讯
Mastering Design Principles: Dependency Inversion in Kotlin
Abstract In modern software engineering, writing code that simply "works" is only the first step. The real challenge lies in designing systems that are maintainable, scalable, and easy to test. This article explores the Dependency Inversion Principle (DIP), the final pillar of the SOLID design principles. Through a practical, real-world example in Kotlin, we will demonstrate how to transition from a tightly coupled architecture to an abstraction-based design. This shift dramatically improves our codebase, facilitates unit testing, and prepares our applications for future growth. Introduction: The Chaos of Coupling As applications grow, it is common to see how a minor change in a database schema or a third-party API triggers a domino effect, breaking unrelated parts of the system. This fragility is a direct consequence of tight coupling. Software design principles, particularly SOLID, were established to prevent this architectural decay. Today, we focus on the "D" in SOLID: the Dependency Inversion Principle (DIP). This principle establishes two core rules: High-level modules should not depend on low-level modules. Both should depend on abstractions (interfaces). Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions. The Scenario: An E-commerce Payment Processor Imagine you are building the billing system for an online store. To process purchases, the system needs to connect to a payment gateway, such as PayPal. The Bad Way: Tight Coupling (Violating DIP) In this initial design, our high-level business logic (OrderProcessor) directly instantiates and depends on the concrete low-level class (PayPalService). // Low-level component (Concrete detail) class PayPalService { fun executePayment(amount: Double) { println("Processing payment of $$amount via PayPal API.") } } // High-level component (Business logic) class OrderProcessor { // Tight coupling: this class depends directly on a concrete implementation private val
AI 资讯
AI is hurting Apple in more ways than one: it may force iPhone price increases
CEO Tim Cook said in a recent interview that the situation is "unsustainable."
AI 资讯
Who Here Has Worked with Legacy? The Longer You Wait, the Worse It Gets
I promised myself that starting this week I'd switch to lighter topics. But on Monday, my JSNation...
AI 资讯
The Korean Telecom Giant at the Center of Anthropic’s Mythos Controversy
Days before Anthropic took its most advanced AI models offline, the White House ordered the company to revoke SK Telecom’s access to Claude Mythos over claims of alleged ties to China.
AI 资讯
A model with R-squared near 0 can still give valid 90% prediction intervals - here's why (and the catch)
I recently calibrated a recovery-rate model that had only two weak features. Its point accuracy was almost nothing — R² basically zero. I expected its uncertainty estimates to be junk too. They weren't: the 90% conformal prediction intervals covered ~89% of held-out outcomes. Valid, just wide . That surprised me enough to nail it down, because it contradicts a belief a lot of us carry around: "my model isn't accurate, so I can't trust its uncertainty." For split conformal prediction, that's backwards. Here's the precise statement, a runnable demo, and the one caveat that actually bites. Coverage is a property of the procedure, not the model Split conformal prediction gives a distribution-free, finite-sample marginal coverage guarantee : P( Y ∈ Ĉ(X) ) ≥ 1 − α and it holds for any point model, as long as the calibration and test data are exchangeable. The model is a black box. You fit it however you like, then on a held-out calibration set you take the (1−α) quantile of the absolute residuals, and that quantile becomes the half-width of your intervals. Nowhere does that construction require the model to be good. A bad model just has large residuals, so the calibration quantile is large, so the intervals are wide — wide enough to still cover at the stated rate. Accuracy doesn't buy you validity ; it buys you efficiency (narrower intervals at the same coverage). The demo (numbers are reproducible, seed fixed) Same dataset and target, three models from strong to useless, target coverage 90%: model R² marginal coverage mean interval width gradient boosting 0.741 0.895 5.39 weak linear (1 noisy feature) 0.061 0.905 10.39 predict-the-mean −0.000 0.907 10.83 All three land at ~90% coverage. The only thing that changes is width: the good model's intervals are half as wide . That's the whole story in one table — validity is constant, efficiency tracks accuracy. import numpy as np from sklearn.linear_model import LinearRegression from sklearn.ensemble import GradientBoostingReg
AI 资讯
What Beginners Get Wrong About IT Certifications
Certifications help when they match a role and are backed by proof — not as a scoreboard. The problem Beginners are told certifications are the key to IT, so they buy the most popular one, pass it, and are surprised when interviews still go badly. A certificate proves you can pass an exam; it does not, on its own, prove you can do the job. Why this matters now Certifications remain useful signals, and official providers like CompTIA, Microsoft, AWS, Cisco and Google keep their exam objectives public and current. But as AI makes it easier to grind practice questions, employers lean harder on whether you can actually apply the knowledge. The value of a certificate is increasingly in what you can demonstrate alongside it. There is also a cost reality. Exams, courses and retakes add up in money and time, and career changers usually have limited amounts of both. Spending three months and a chunk of savings on a certificate that no target role actually asks for is one of the most common and most avoidable mistakes in an IT transition — which is exactly why the order you choose them in matters. The practical framework Use certifications as targeted evidence, not as a scoreboard. Three rules: Match objectives to a job. Open the certification's published objectives next to a real job description. Overlap means it is relevant; no overlap means it is a hobby. Prove the same skills in practice. For each major objective, build one small artefact that shows you can do it, not just recall it. Stop at enough. One well-chosen, well-demonstrated certification beats three unrelated ones. Sequence them to roles, not to availability. Which one first? Let the target role decide, not the brand with the loudest marketing. As a rough guide: a vendor-neutral foundation (such as CompTIA A+ for general IT support, or Network+/Security+ as you specialise) suits broad support roles; a cloud-fundamentals exam (Microsoft Azure or AWS) suits cloud-leaning roles; Cisco-flavoured paths suit networkin
AI 资讯
Saga Orchestration in Go: Distributed Workflows That Actually Roll Back
Every non-trivial business operation touches more than one system. An e-commerce order reserves inventory, charges a payment method, and schedules a shipment — three services, three databases. A bank transfer debits one account and credits another across two ledgers that may not even be in the same data center. A cloud VM provisioning workflow reserves a network port, allocates storage, starts the hypervisor, registers billing, and sends a notification — five services, five independent state stores. The question is: what happens when step four fails after steps one through three have already succeeded? In a monolith backed by a single database, the answer is simple: roll back the transaction. The database engine guarantees atomicity; either everything commits or nothing does. But when your workflow spans multiple services, each owning its own storage, there is no transaction boundary that wraps them all. There is no rollback button. Step one through three have already made durable changes to systems that do not know about each other, and step four's failure has left the system in an inconsistent state. This is not a pathological edge case. It is the default condition in any distributed architecture. And it gets worse: the failure might not be a hard error. The network might time out. The billing service might return a 503. You do not know whether step four applied its effect or not — you only know you did not receive a success response. Now what? This is the problem sagas were designed for. Client Inventory Svc Payment Svc Shipping Svc │ │ │ │ 1 │──reserve(item)──►│ │ │ │◄──── 200 OK ─────│ │ │ │ [reserved ✓] │ │ │ │ │ │ 2 │──────────── charge(card, $99) ────►│ │ │◄───────────────── 200 OK ──────────│ │ │ │ [charged ✓] │ │ │ │ │ 3 │─────────────────────── schedule(order) ─────────────►│ │◄─────────────────────────── 503 ──────────────────── │ │ │ │ [no record ✗] │ │ │ │ ╔══════════════════════════════════════════════════════╗ ║ ⚠ Inconsistent state ║ ║ Inventory: it
AI 资讯
The Dependency Injection Quest: How I Turned Spaghetti Code Into a Lightsaber 🚀
The Quest Begins (The “Why”) Picture this: I’m knee‑deep in a legacy codebase that feels like the Death Star’s trash compactor—every time I try to add a feature, the walls close in and I’m squashed by tight coupling. I’d just spent three hours tracking down a bug that only showed up when the payment gateway was mocked in a test. The culprit? A new PaymentGateway() buried deep inside an OrderService class. It was like trying to defeat Darth Vader with a butter knife—no matter how hard I swung, the Dark Force (aka hidden dependencies) kept pulling me back. I realized I was instantiating collaborators inside the very classes that should be oblivious to their implementation details . The result? Tests that needed a real database, a real Stripe account, and a sacrificial goat to run. Any change to a third‑party API meant hunting down every new scattered across the project. Onboarding a new teammate felt like handing them a map written in ancient Sumerian. Honestly, I was ready to quit coding and become a professional napper. Then, during a late‑night coffee‑fueled refactor session, I stumbled upon a tiny line of documentation that whispered: “Depend on abstractions, not concretions.” It sounded like Yoda giving me a pep talk. The Revelation (The Insight) The magic spell I uncovered is Dependency Injection (DI) —specifically, constructor injection . Instead of a class creating its own collaborators, we hand them in from the outside. Think of it as giving a Jedi their lightsaber rather than making them forge one in the middle of a battle. Why does this feel like discovering the Force? Testability explodes – you can swap in fakes, mocks, or stubs without touching production code. Flexibility skyrockets – swapping a payment provider becomes a one‑line config change, not a scavenger hunt. Clarity reigns – the constructor becomes an honest inventory of what a class needs to do its job. The moment I applied it, the codebase felt lighter, like Luke finally trusting the Force ins
AI 资讯
The iPhone Air 2 will reportedly land next spring with a second camera
The ultralight may become a permanent fixture in Apple's smartphone lineup.