今日已更新 263 条资讯 | 累计 23846 条内容
关于我们

标签:#STEM

找到 159 篇相关文章

AI 资讯

The Future of Rust: Dominating Systems Programming in 2026

The Future of Rust: Why This Memory-Safe Language is Dominating Systems Programming in 2026 In its early years, Rust was often viewed as a "rising star"—a promising language with significant potential but a steep learning curve. As we navigate through 2026, that narrative has fundamentally shifted. Rust has transitioned from a niche interest to a cornerstone of modern, memory-safe infrastructure. The language is no longer just proving its worth; it is defining the gold standards for systems programming, cloud-native backend services, and kernel development. This deep dive explores the key pillars driving Rust's evolution, its massive ecosystem growth, and the roadmap for the years ahead. Seamless Ownership: The New Era of Rust Ergonomics One of the most significant shifts in recent Rust development has been the relentless focus on language ergonomics. Historically, developers occasionally felt that custom smart pointers were "second-class citizens" compared to built-in references. The "Beyond the & " initiative has successfully bridged this gap. Through advancements in Smart Pointer Parity , developers can now use custom pointers—such as Rc , Arc , or specialized interop pointers—with the same intuitive syntax and capabilities as standard references. Furthermore, the introduction of sophisticated field projection mechanisms and &own references allows for unprecedented precision in managing ownership and borrowing. This makes complex data structures much easier to implement and reason about, drastically reducing the friction typically associated with high-level abstractions. The Async Revolution: Making Asynchronous Code Natural Rust has achieved a milestone often referred to as "Async Parity," aiming to make asynchronous programming feel as natural and seamless as synchronous code. Several key developments have fueled this revolution: Async-in-Traits: The stabilization of async fn in traits has removed the need for external crates like async-trait , greatly simplify

2026-07-16 原文 →
AI 资讯

Load Balancing: The Neo Way to Dodge Traffic

The Quest Begins (The “Why”) I still remember the night our API started to sputter under a sudden traffic spike. Users were seeing 502 errors, the monitoring dashboard looked like a neon rainstorm, and I felt like I was stuck in a lobby waiting for the elevator that never arrives. We had a simple round‑robin load balancer sitting in front of three identical services. It worked fine when traffic was smooth, but as soon as a burst hit, one node would get overloaded while the others twiddled their thumbs. Honestly, I thought we just needed more servers. Throwing hardware at the problem felt like using a sledgehammer to crack a nut—expensive and messy. After a few frantic Slack threads and a lot of coffee, I realized the real issue wasn’t capacity; it was how we distributed the work. The balancer was oblivious to the actual load on each backend, treating every request like it was the same weight. That moment became my quest: design a load balancer that reacts to real‑time load, stays simple enough to operate, and doesn’t cause a reshuffling nightmare when we scale the cluster. The Revelation (The Insight) The breakthrough came when I read about least‑connections load balancing combined with a slow‑start period for new hosts. The core insight is deceptively simple: Send each new request to the backend that currently has the fewest active connections. Why does that work? Immediate fairness – If one node is handling long‑running requests, it will naturally have a higher connection count and receive fewer new ones until it catches up. Burst absorption – During a traffic spike, requests spill over to the less‑busy nodes instead of piling onto a single overloaded instance. Predictable scaling – When we add a new server, it starts with zero connections, so it gets a fair share of traffic right away—but we temper that with a slow‑start window to avoid overwhelming a cold host. Compare that to round‑robin, which blindly cycles through the list regardless of each node’s state. In

2026-07-15 原文 →
AI 资讯

Is Being Full-Stack Really Necessary in the Age of AI?

In an AI-powered reporting project, the backend API response time suddenly jumped to 8 seconds; I couldn't find a solution by examining only the frontend code to isolate the issue. This experience highlighted how the lack of a full-stack developer, who can see API, data layer, and model integration simultaneously, can slow down a project. Below, I will analyze step-by-step whether being full-stack is truly necessary in the age of AI. Why is Being Full-Stack Necessary in the Age of AI? The primary benefit of being full-stack is enabling a single developer to have end-to-end control of AI systems. This is because training a model, saving it to a vector database, and serving it via a REST API all occur at different layers; each of these layers might require a separate area of expertise. However, a full-stack developer, by being able to see the entire process from the data collection script ( python collect_data.py ) to the model service ( uvicorn app:app --host 0.0.0.0 ), can catch integration errors faster. Let's illustrate this advantage with a concrete example: within a project, I automated model retraining using a systemd timer and saw “Active: active (waiting)” in the systemctl status model-retrain.timer output; however, the API layer's GET /predict response was still returning the old model. Identifying the issue was only possible by simultaneously examining the timer configuration and the API code; without switching between separate teams. Summary: Full-stack proficiency provides the ability to detect and resolve potential incompatibilities within the complex data-model-service chain of AI projects at a single point. How Do Full-Stack Skills Contribute to AI Projects? A full-stack developer keeps all steps, from data preprocessing ( pandas script) to the model service ( FastAPI endpoint), within a single codebase. This simplifies version control and the CI/CD workflow. For example, when I define a postgres service, a redis cache, and an api service within docker

2026-07-15 原文 →
AI 资讯

Scale Is a Design, Not a Dial

The dashboard says forty instances, up from twelve this morning. The autoscaler did its job: it saw latency climb and threw hardware at it. And latency got worse. Not flat. Worse. You're paying for three times the compute to serve a slower product. Somewhere under all forty of those boxes is a single thing they're all waiting in line for, and every instance you add makes the line longer. Horizontal scaling multiplies work that doesn't have to coordinate. The instant the work does have to coordinate, more instances make it slower. Amdahl wrote this down in 1967: the serial fraction of a job sets a hard ceiling on how much faster you can go, no matter how much hardware you throw at the parallel part. Neil Gunther's Universal Scalability Law goes further: past a certain point, the cost of nodes coordinating with each other bends the curve back down. Add capacity, get less throughput. That ceiling was not set by the autoscaler, and it will not be moved by the autoscaler. It was set a long time before this morning, in a room, by whoever decided where the state lives and who has to touch it at the same instant. Now hand the service to a fleet of agents. It writes you something that looks built to scale: stateless handlers, a tidy repo, green tests, a canary that bakes fine at 1% traffic. Every gate you trust says ship it. And the bottleneck is sitting right there in the design, invisible to all of it, because the mistake isn't in the lines, it's in the shape. You cannot catch a shape problem by reading a diff. Name the hot state before you pick a framework. Where does the contended state live, and which requests touch it at the same instant? Answer that out loud, before anyone opens an editor. The tool is downstream of that answer, every time. Originally published at https://imacto.com/writing/scale-is-a-design-not-a-dial . Written with Claude Opus 4.8.

2026-07-15 原文 →
AI 资讯

Cybersecurity 101 : Windows Notifications

Introduction So imagine you are focused on your cappuccino-frappuccino doing something very important on you win laptop and then have a cringe attack due to the unknown Phone Link notification : Complete linking devices Your PC and mobile device are almost linked. Click here to continue linking devices. via Phone Link Then you switch off bluetooth, wifi, laptop - and you are right. What to do next ? Basic checks Settings -> Bluetooth & devices -> Mobile devices Settings -> Accounts -> Email & accounts Inspect recent notifications in Event Viewer eventvwr.msc Applications and Services Logs └ Microsoft └ Windows └ Notifications Applications and Services Logs └ Microsoft └ Windows └ Shell-Core Digital forensics Windows stores toast notifications in a local database, hence you need to install sqlite Get-ChildItem " $ env : LOCALAPPDATA \Microsoft\Windows\Notifications" output : Directory: C:\Users\$ USERNAME \A ppData \L ocal \M icrosoft \W indows \N otifications Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 1/1/2026 0:00 AM wpnidm -a---- 1/1/2026 0:00 AM 1000000 wpndatabase.db -a---- 1/1/2026 0:00 AM 10000 wpndatabase.db-shm -a---- 1/1/2026 0:00 AM 1000000 wpndatabase.db-wal wpndatabase.db is a SQLite database. connect to the database : sqlite3 " $env :LOCALAPPDATA \M icrosoft \W indows \N otifications \w pndatabase.db" query the Notification table . headers on . mode column SELECT Notification . Id , Notification . HandlerId , Notification . Type , Notification . ArrivalTime , Notification . Payload FROM Notification LIMIT 20 ; Then you will have something like : Id: [REDACTED] HandlerId: [REDACTED] Type: toast ArrivalTime: [REDACTED] Payload: <?xml version="1.0"?> <toast activationType= "protocol" launch= "ms-phone:fre/?cid=[REDACTED]&ref=FreIncompleteToast&reason=IncompleteNotificationsToast" > <visual> <binding template= "ToastGeneric" > <text hint-maxLines= "1" > Complete linking devices </text> <text> Your PC and mobile device are almost li

2026-07-14 原文 →
AI 资讯

Treat Per-Task Model Switching as a Concurrency Protocol

Changing the model for a running AI task is not a settings update. It is a distributed operation: read current task -> prepare credentials/config -> request restart -> receive result -> persist active model If two switches overlap, completion order can differ from request order. The system needs a rule for which intent wins. The concrete case At commit c58bcd4 , MonkeyCode records model-switch attempts with from/to model IDs, request ID, load-session flag, success, message, session ID, and timestamps in TaskModelSwitch . The reviewed task use case creates a switch record, asks taskflow to restart with the target model configuration, and completes the switch record and task model based on the response. The accompanying tests cover success and failure paths. From this source review, I could not establish an explicit compare-and-swap generation or a per-task serialization contract around overlapping requests. That does not prove an exploitable race: serialization may exist elsewhere in the deployment or taskflow boundary. It means concurrency semantics deserve an explicit test and contract. Why last completion is unstable Assume request A selects model A, then request B selects model B: time -> A: request ---- restart ---------------- complete B: request -- restart -- complete If each successful completion writes its model, B applies first and late A overwrites it. Reverse network timing and the result changes. The companion simulator makes that order dependence visible: export function naiveCompletionOrder ( completions ) { let model = " initial " ; for ( const completion of completions ) { if ( completion . success ) model = completion . model ; } return model ; } [A, B] ends on B. [B, A] ends on A. The caller's latest intent is not part of the rule. Add a monotonic generation Assign a generation while accepting each request: A -> generation 41 B -> generation 42 Completion may update active state only when its generation equals the task's current requested generatio

2026-07-14 原文 →
AI 资讯

LLM Evaluation System Prompts Scored Rubrics Runtime Guardrails: A Practical Guide for Production

LLM Evaluation System Prompts Scored Rubrics Runtime Guardrails: A Practical Guide for Production Learn how to evaluate LLM outputs in production using system prompts, scored rubrics, and runtime guardrails to prevent hallucinations and ensure quality. TL;DR: To evaluate LLM outputs in production, combine system prompts that define evaluation criteria, scored rubrics using LLM-as-a-judge for dimensions like correctness and relevance, and runtime guardrails that filter or flag unsafe outputs. This approach scales better than human review, adapts via prompt changes, and catches failures that status codes miss, as seen in the Air Canada chatbot case. Why Production LLM Evaluation Demands More Than Status Codes A 200 status code only confirms the server processed the request—it says nothing about whether the generated text is factual, safe, or useful. The Air Canada chatbot that invented a non-existent bereavement discount returned perfectly valid HTTP responses, yet the hallucinated policy led to a tribunal ruling against the airline. Production evaluation must therefore separate operational health (latency, error rates) from output quality (correctness, relevance, harmlessness). Consider a typical API call that succeeds operationally but fails qualitatively: import requests response = requests . post ( " https://api.example.com/v1/chat " , json = { " model " : " gpt-4o " , " messages " : [{ " role " : " user " , " content " : " What is Air Canada ' s bereavement policy? " }]}, headers = { " Authorization " : " Bearer $KEY " } ) print ( response . status_code ) # 200 print ( response . json ()[ " choices " ][ 0 ][ " message " ][ " content " ]) # Output: "Air Canada offers full refunds for bereavement-related cancellations..." A 200 status code and a well-formed JSON body mask a completely fabricated policy. To catch this, you need a separate evaluation layer that scores the output against a rubric. LLM-as-a-judge is a common approach, using a second model to assess the

2026-07-14 原文 →
AI 资讯

How DoorDash Built an AI Shopping Assistant That Doesn’t Rely on the LLM Alone

DoorDash details the architecture behind Ask DoorDash, its AI-powered conversational shopping assistant, combining LLMs, specialized AI agents, MCP-based tooling, and an intelligence layer with persistent consumer memory and live backend data. Early results show up to 24% higher checkout conversion, 17% larger baskets, and improved intent accuracy using memory-backed sessions. By Leela Kumili

2026-07-13 原文 →
AI 资讯

Failure Engineering Explained by Uncle to Nephew — Episode 2: Types of Failures

Episode 1 established the mindset: failure is normal, not a sign of bad engineering. Episode 2 gets specific — you can't detect or handle a failure you can't even name. Saturday, Round 2 👦 Nephew: Uncle, last time you convinced me failure is basically guaranteed. Fine, I accept it. So what actually fails ? 👨‍🦳 Uncle: You tell me. Start listing things that could go wrong in your app right now. 👦 Nephew: Uh... the server could crash. The database could go down. My code could have a bug. 👨‍🦳 Uncle: Keep going. 👦 Nephew: The network? Someone could deploy the wrong thing? Payment gateway dies mid-checkout? 👨‍🦳 Uncle: You just named six of the seven categories without trying. You already know this. You've just never sorted it. 1. Hardware Failure 2. Software Failure 3. Network Failure 4. Database Failure 5. Third-Party Failure 6. Human Error 7. Resource Exhaustion 👦 Nephew: Then why do we need the list at all, if I already know it instinctively? 👨‍🦳 Uncle: Because "instinctively" isn't fast enough at 2 AM. Let's trace each one properly. Part 1 — Hardware Failure 👦 Nephew: This one's obvious anyway — I deploy to AWS. The cloud hides hardware failure from me. 👨‍🦳 Uncle: Does it? 👦 Nephew: ...doesn't it? That's the whole point of paying for EC2 instead of buying a server. 👨‍🦳 Uncle: Let's trace it. Your app sits on an EC2 instance. What's underneath the instance? 👦 Nephew: Virtual machine stuff, I guess? 👨‍🦳 Uncle: And underneath that ? 👦 Nephew: ...an actual physical machine somewhere. In a data center. 👨‍🦳 Uncle: There it is. Your app | "Virtual" server (EC2/Droplet) | ACTUAL physical hardware somewhere in a data center | Still capable of failing — just less visible to you 👦 Nephew: So it's not hidden. It's just one layer further away than I thought. 👨‍🦳 Uncle: Exactly. AWS absorbs a lot of it — that's part of what you're paying for — but disks still fail, instances still get abruptly terminated, whole availability zones still go down. That's Hardware Failure . Hardware Fa

2026-07-12 原文 →
AI 资讯

Designing a Multi-Tenant Storefront With Wildcard Subdomains

At my workplace, I worked on an ERP platform used by fashion businesses to manage customers, body measurements, products, orders, invoices, inventory, staff, and other day-to-day operations. Each business also had a public storefront where customers could browse products and check out. The storefront started as a simple sharing feature. Businesses could publish products, copy a link, and send it to customers outside the main workspace. That worked well because the storefront was mostly a product catalogue, and most of the sales process still happened after the customer contacted the business. As the platform evolved, the storefront became much more than a catalogue. Customers were discovering businesses through shared links, browsing products, placing an order, and tracking orders directly from the storefront. That introduced new technical requirements around branded storefronts, SEO, server-rendered metadata, public checkout, pricing, and analytics. This article explores how I designed the storefront around wildcard subdomains, immutable shop identities, server-side shop resolution, and a scalable analytics pipeline. Table of Contents Giving the Storefront Its Own Identity Business Names, Reserved Names, and Subdomains Resolving a Storefront Active and Inactive Storefronts Location and Currency Product Pages and Share Previews Storefront Event Ingestion Processing Raw Events Counting Unique Visitors With HyperLogLog Domain Routing and Local DNS 1. Giving the Storefront Its Own Identity The original storefront was fairly simple. It was a React application that fetched a business and rendered its products. Beyond that, there wasn't much to it. There were no branded storefronts, analytics, subdomains, or even a separate identity beyond the business itself. Introducing those capabilities meant the storefront needed its own data model. I introduced a dedicated shop entity to represent the public storefront. The business remained the source of operational data such as cu

2026-07-12 原文 →
AI 资讯

Building an Instagram AutoDM System at Scale: Webhooks, Event Driven Architecture, and Lessons Learned

Instagram creators love engagement. Every comment is an opportunity to start a conversation, share a product, deliver a resource, or convert a viewer into a customer. The problem is that manually replying to hundreds or thousands of comments doesn't scale. At Vyral , we set out to build an Instagram AutoDM platform capable of serving thousands of creators while handling bursts of traffic generated by viral Reels. Instead of building a traditional chatbot, we designed an event driven system powered by Instagram webhooks, AWS services, and asynchronous processing. This article walks through the architecture, the engineering challenges we encountered, and the lessons we learned while designing a system that can process large spikes of comment events reliably. The Problem Imagine a creator with 2 million followers. A Reel starts trending. Within minutes: 10,000+ comments arrive Thousands of users comment the same keyword Instagram sends webhook events continuously Every eligible comment should trigger a personalized DM From an engineering perspective, this isn't a chatbot problem. It's an event processing problem. The system needs to answer questions like: Which comments qualify? Has this comment already been processed? What happens if Instagram sends the same webhook twice? What if the user deletes the comment? What if our service is temporarily unavailable? How do we avoid overwhelming downstream APIs? Those questions shaped the architecture far more than the messaging logic itself. Why We Chose Webhooks Instead of Polling Polling Instagram every few seconds would have introduced unnecessary latency and API usage for Vyral AutoDM . Instead, Instagram pushes events whenever something happens. The flow looks like this: Instagram │ ▼ Webhook Endpoint │ ▼ Event Validation │ ▼ Event Queue │ ▼ Workers │ ▼ Business Rules │ ▼ Send DM This architecture offers several benefits: Low latency Lower infrastructure cost Better scalability Natural decoupling between components Most i

2026-07-12 原文 →
AI 资讯

Your Loading Spinner Has an Emotional Job. Is It Doing It?

Most of us treat design systems as a functional problem: consistent colors, consistent spacing, consistent components. That part's solved for most teams now. The part nobody writes down is tone. How should this loading state feel? Should this error feel scary or manageable? Is this confirmation message robotic or human? Here's what I've learned paying attention to that layer. Four moments that carry the emotional weight In any app, four states do most of the emotional work: Loading Error Empty Success Get these four right and the whole product feels better, even if nothing about the actual functionality changed. ** Loading: ambiguity feels worse than the wait itself** jsx // Vague, slightly anxious < Spinner /> // Specific, calmer < div className = "loading-state" > < Spinner /> < p > Fetching your latest data... </ p > </ div > A spinner with no context makes people wonder if something's frozen. A spinner with a short label tells them exactly what's happening. Same wait time, different feeling. Errors: same bug, different emotional outcome jsx // Robotic " Error: Request failed with status 500 " // Human " Something went wrong on our end. Your changes weren't lost, try again in a moment. " The second version does three things the first doesn't: it's plain language, it removes blame from the user, and it tells them what to do next. That's the difference between an error that frustrates and one that reassures. Success: robotic vs genuine jsx // Robotic " Action completed successfully. " // Human " Done! Your changes are saved. " This message shows up constantly across a typical app. If it reads like a system log every time, the product feels cold. A small rewrite makes it feel like a person is on the other end. Micro-interactions: timing is part of tone too `jsx// No feedback during the wait, feels broken <button onClick={handleSave}>Save</button> // Immediate feedback, feels responsive <button onClick={handleSave}> {isSaving ? "Saving..." : "Save"} </button>` A butt

2026-07-11 原文 →
AI 资讯

The Complete TypeScript Mastery Guide

Learn TypeScript From First Principles to Senior/Staff-Level Production Engineering If you searched for how to learn TypeScript properly — not just the syntax, but the thinking behind it — this guide is built for that. Most TypeScript tutorials stop at "here's an interface, here's a generic." This one goes further: it's a single, exhaustive TypeScript tutorial and reference that walks through the type system, object-oriented programming, generics, async programming, design patterns, SOLID and DRY principles, error handling, testing, and the tooling that real production teams run in CI — the same TypeScript best practices used at top-tier engineering organizations. Whether you're a beginner looking for a structured TypeScript for beginners path, or an experienced JavaScript developer making the jump to advanced TypeScript and system design, you can read this end to end or jump straight to the section you need using the linked table of contents below. Table of Contents 1. Introduction — What Is TypeScript & Why It Exists 2. Installation, Setup & tsconfig.json Deep Dive 3. Variables & the Complete Type System 4. Functions — Every Form, Overloads, this , and Best Practices 5. Arrays & Tuples 6. Objects & Type Aliases 7. Interfaces 8. Enums & Literal Types 9. Union, Intersection & Discriminated Unions 10. Type Narrowing, Assertions & Type Guards 11. Classes & Object-Oriented Programming 12. Generics — Basic to Advanced 13. Modules, Namespaces & Project Structure 14. Asynchronous Programming — Event Loop to Production Patterns 15. Advanced/Utility Types & the Type-Level Programming Toolkit 16. Design Patterns in TypeScript 17. SOLID, DRY, KISS, YAGNI — Principles Applied With Real TS Code 18. Error Handling Strategies 19. Testing TypeScript 20. Tooling, Linting, Build Systems & CI/CD for Production TS 21. Performance, Compiler Internals & Scaling Large Codebases 22. Interview Cheat Sheet (Expanded) 23. One-Page Quick Revision Sheet 1. Introduction — What Is TypeScript & W

2026-07-11 原文 →
AI 资讯

How Reddit Stores Comment Trees and Ranks Hot Posts

Reddit looks simple and hides two genuinely hard problems. Comments nest arbitrarily deep, and a naive tree structure makes loading a busy thread slow. The front page reorders itself constantly, so ranking cannot just count votes or old posts would never leave. Both problems have well-known answers, and both are good lessons in choosing the right model. The core problem A comment thread is a tree. Each comment can reply to any other, so depth is unbounded. If you store only "this comment's parent id" and then try to load a whole thread, you walk the tree one level at a time, one query per level, which gets slow for deep or wide threads. Loading a popular post with thousands of nested comments should not take thousands of queries. Ranking is the second problem. If the front page sorted by raw vote count, the highest-voted post of all time would sit at the top forever. If it sorted by newest, quality would drown in noise. You need a score that blends how good a post is with how fresh it is, so good new posts can climb and old ones fade even if they were once popular. Key design decisions Store the parent pointer, but do not traverse at read time. The simple model is a parent_id per comment, which is easy to write but expensive to read as a tree. To load a thread cheaply, fetch all comments for the post in one query, then assemble the tree in application memory. One read, in-memory tree building. This works because a single post's comments, while numerous, fit in memory to assemble. Consider a path or closure model for deep trees. For very deep threads, some systems store a materialized path on each comment, an encoded ancestor chain, so you can fetch an entire subtree with a single prefix query and sort by the path to get correct display order. Another option is a closure table that records every ancestor-descendant pair, which makes subtree queries direct at the cost of extra write work. The right choice depends on how deep threads get and how often you read subtrees

2026-07-10 原文 →
AI 资讯

How Elasticsearch Searches Fast: The Inverted Index and Shard Routing

Searching billions of documents for a phrase and getting ranked results in tens of milliseconds looks like magic. It is not. It comes down to two ideas working together: an index that maps words to documents instead of scanning documents for words, and a way to spread that index across machines so each holds only a slice. Understand both and full-text search stops being mysterious. The core problem A database scans rows. If you ask a plain database to find every document containing a word, it reads documents and checks them, which is linear in the amount of data. That is fine for exact key lookups and hopeless for free-text search across huge corpora. You need the opposite mapping. Instead of "given a document, what words does it have", you want "given a word, which documents have it". That inversion is the whole trick. The second problem is size. One machine cannot hold the index for billions of documents, and one machine cannot serve the query load. So the index has to be split across nodes, and a query has to find the right nodes and combine their answers. Key design decisions Build an inverted index. At index time, each document is broken into tokens by an analyzer that lowercases, splits on word boundaries, and often strips or stems words. For every token, the engine keeps a posting list: the set of document ids that contain it, often with positions for phrase matching. A query for a word becomes a direct lookup of its posting list, not a scan. A multi-word query intersects or unions posting lists, which is fast because the lists are sorted. Store the index in immutable segments. New documents go into small new segments rather than editing existing ones. Segments are immutable, which makes them cache-friendly and safe to read without locks. A background process merges small segments into larger ones over time. A delete is just a marker; the document is removed for real during a later merge. Split an index into shards. An index is divided into shards, each a sel

2026-07-10 原文 →
AI 资讯

Architecture Decisions Behind Building a Simple Personal Software Tool

How I moved from a traditional web application mindset to exploring local-first architecture I wanted to build a simple software tool for my personal use. Nothing complicated. Something in the category of tools people build for themselves: A personal expense tracker A budgeting application A private knowledge management tool A personal organization system The important characteristic was this: The data belonged to one person. It was not a social application. It was not a collaboration platform. It did not need users interacting with each other. There was no requirement for: Public profiles Sharing updates Real-time collaboration Social features It was simply a tool that helped one person manage their own information. When I started thinking about building it, my first instinct was the most natural one for me. I am a web application developer. My comfort zone is building web applications. So my first thought was: "Why not build a Ruby on Rails application?" Something like: User | Web Application | Ruby on Rails API | PostgreSQL Database This is an architecture I have worked with many times. The workflow is familiar: Create models Build controllers Add authentication Store data in a database Deploy the application Access it from anywhere This is a proven architecture. For many products, this is exactly the right approach. But while thinking about this project, I asked myself a different question: Am I choosing this architecture because the problem requires it, or because it is the architecture I already know? That question changed the direction completely. Understanding The Actual Problem Before choosing technology, I wanted to understand the nature of the problem. What kind of application was I actually building? There is a big difference between building: A social network A marketplace A collaboration platform A communication application versus building: A personal tool A private utility A single-user productivity application In the first category, the server is the

2026-07-09 原文 →
AI 资讯

The Hidden Cost of Multi-Model Workflows

The AI race is quietly changing Months ago, most discussions revolved around one question: "Which model is the smartest?" Today, I'm seeing a different pattern. The conversation is shifting toward: How do we orchestrate multiple models, tools, and workflows effectively? Look at where the industry is investing. It's no longer just about improving the model itself. The focus is increasingly on long-running tasks, delegated execution, tool use, coding assistants, planning, memory, and specialized sub-tasks working together. That's not a coincidence. The model is becoming one component of a much larger system. As engineers, we're spending less time debating benchmarks and more time designing the layer around the model: • Context management • Routing requests to the right model • Memory and continuity • Tool orchestration • Verification and evaluation • Recovery and fallback strategies This is why I believe the next competitive advantage won't simply be having access to the "best" LLM. It will be building the best AI Harness—the engineering layer that coordinates models, tools, context, and decision-making into a reliable system. Cloud computing went through a similar evolution. Eventually, the infrastructure became a commodity, while orchestration became the differentiator. I think AI is heading down the same path. In a few years, we may stop asking: "Which model are you using?" and start asking: "What's your orchestration architecture?" I'm curious—are you seeing the same shift in your AI workflows, or do you think model capability will remain the primary differentiator?

2026-07-09 原文 →
AI 资讯

End-to-end Design Walkthrough — Full System Design

Full system design walkthrough: vì sao quy trình 5 bước quan trọng hơn thuật ngữ, và cái bẫy nhảy thẳng vào deep-dive Một buổi phỏng vấn system design 45–60 phút không đánh giá xem thí sinh biết bao nhiêu tên công nghệ, mà đánh giá xem thí sinh có xử lý được một bài toán mơ hồ theo một quy trình có kỷ luật hay không. Cùng đề "thiết kế URL shortener", người thất bại thường bắt đầu bằng "dùng Cassandra vì scale tốt" ngay ở phút thứ hai — chưa hỏi scale bao nhiêu, chưa biết read/write ratio, chưa đồng ý interface. Người pass đi theo một trình tự cứng: requirements → estimation → high-level → deep-dive → tradeoff . Cùng một đề, cùng thời lượng, nhưng người thứ hai dẫn dắt được interviewer thay vì bị dí. Bài này mô tả quy trình đó ở mức thực dụng, các thất bại thường gặp khi bỏ bước, và một hands-on end-to-end trên URL shortener để tự luyện. Cơ chế hoạt động Quy trình chuẩn được nhiều tài liệu tổng hợp (Alex Xu — System Design Interview vol.1; Donne Martin — system-design-primer ; Kleppmann — Designing Data-Intensive Applications ) đều có 4–5 bước gần như trùng nhau. Đây là khung 5 bước dùng thực tế trong phỏng vấn: Requirements clarification (~5 phút). Chốt functional requirement (hệ thống làm gì — API nào, use case nào) và non-functional requirement (availability target, latency target, consistency yêu cầu, security, cost). Không đoán — hỏi lại interviewer. Output: 3–5 gạch đầu dòng functional + 3–5 gạch NFR + danh sách "out of scope" (analytics, billing, ...). Back-of-the-envelope estimation (~5 phút). Tính DAU, QPS peak/avg, read:write ratio, storage growth theo năm, bandwidth. Không cần chính xác — cần đúng order of magnitude để quyết định "cần shard hay không", "cache có ý nghĩa không", "một node đủ hay phải scale ngang". High-level design (~10–15 phút). Vẽ box diagram: client → LB → app tier → cache → primary datastore → async worker → object storage/CDN. Định nghĩa API (endpoint, request/response, status code) và data model (schema chính, index chính). Ở bước này

2026-07-08 原文 →
AI 资讯

Left of the Loop: The PO is Dead, Long Live the PO

When I wrote about shifting the engineering process left — spec sessions, autonomous agents, humans reviewing output rather than writing code — a question kept coming up. Where does the Product Owner fit in all of this? It’s the right question. And I think the answer is more interesting than “the PO disappears.” Let’s start with acceptance criteria. We invented them to bridge a gap. The team needed to know when something was done. The PO needed confidence that what got built matched the intent. Acceptance criteria were the contract between the two. But if the Spec Session is where intent gets defined — by the whole team, together, before the agent runs — that gap closes. What the team agreed on in the room is the definition of done. The spec is the acceptance criteria. You don’t need a separate validation step because the planning and the agreement happened at the same time. The tighter the loop, the less ceremony you need around it. There’s a caveat though. The spec is a necessary contract. It’s not a sufficient one. Simon Martinelli’s work on the AI Unified Process validates the spec-driven approach technically. But his model is about the artifact — requirements at the center, AI generating everything else from them. How the team actually builds shared understanding before the spec exists isn’t something it addresses. That’s not a criticism. It’s just a different question. A spec written after a real Spec Session — where the team worked through edge cases together, disagreed, got to resolution — is different from a spec written by one person and signed off asynchronously. Same artifact. Different quality of shared understanding. That distinction matters when the agent hits an edge case the spec didn’t anticipate. So what’s actually left for a dedicated PO? Two things. And they’re very different. The first is product thinking — challenging intent, representing user needs, asking why before the agent runs with something. That’s valuable. But it doesn’t require a ded

2026-07-07 原文 →