The Paradox of Fancy Tooling
submitted by /u/fagnerbrack [link] [留言]
找到 8804 篇相关文章
submitted by /u/fagnerbrack [link] [留言]
Engineering posts often end with: The new design is correct, scalable, and fast. Fast compared with what? When we changed Podium so tied players rank by arrival time instead of player ID, we added: a Lua script; a per-leaderboard sequence; a public-ID mapping; a second sorted set for ascending order. That design is fairer. It is also impossible for it to be free. So we built two benchmark layers: direct Redis strategy benchmarks to isolate the data-model cost, and end-to-end HTTP benchmarks to show what users actually experience. We are publishing the results, including the regression, because performance claims are useful only when readers can inspect the workload and reproduce the measurement. TeneficGames / podium High-performance, Redis-backed leaderboards for games and competitive applications. Podium High-performance, Redis-backed leaderboards for games and competitive applications. Podium provides ready-to-run HTTP and gRPC APIs for scores, ranks, seasons, and player-relative views. It is designed for backend teams operating large fleets of independent leaderboards without provisioning each leaderboard in advance. Fair, deterministic ordering when scores are equal. Single and bulk score updates, including multi-leaderboard fan-out. Standalone Redis and real Redis Cluster integration coverage. Deploy one multi-architecture OCI image with Docker, containerd, Kubernetes or another OCI-compatible runtime. Quickstart · Performance · API · Documentation · Helm chart · Docker Hub · GHCR Quickstart Start Redis 8.2 and the latest stable Podium image: docker network create podium docker run --detach --name podium-redis --network podium redis:8.2-alpine docker run --detach --rm --name podium \ --network podium \ --publish 8880:8880 \ --publish 8881:8881 \ --env PODIUM_REDIS_HOST=podium-redis \ --env PODIUM_REDIS_PORT=6379 \ trungdlp/podium:latest start Verify the service: curl http://localhost:8880/healthcheck WORKING Submit two equal scores: curl --request … View on Gi
A leaderboard looks like a one-command problem: ZADD weekly 100 alice ZADD weekly 100 bob ZREVRANGE weekly 0 -1 WITHSCORES While building Podium , an open-source Redis-backed leaderboard service, we discovered that the difficult part begins when two players have the same score. We are sharing the design because this edge case can silently turn player IDs into ranking rules. TeneficGames / podium High-performance, Redis-backed leaderboards for games and competitive applications. Podium High-performance, Redis-backed leaderboards for games and competitive applications. Podium provides ready-to-run HTTP and gRPC APIs for scores, ranks, seasons, and player-relative views. It is designed for backend teams operating large fleets of independent leaderboards without provisioning each leaderboard in advance. Fair, deterministic ordering when scores are equal. Single and bulk score updates, including multi-leaderboard fan-out. Standalone Redis and real Redis Cluster integration coverage. Deploy one multi-architecture OCI image with Docker, containerd, Kubernetes or another OCI-compatible runtime. Quickstart · Performance · API · Documentation · Helm chart · Docker Hub · GHCR Quickstart Start Redis 8.2 and the latest stable Podium image: docker network create podium docker run --detach --name podium-redis --network podium redis:8.2-alpine docker run --detach --rm --name podium \ --network podium \ --publish 8880:8880 \ --publish 8881:8881 \ --env PODIUM_REDIS_HOST=podium-redis \ --env PODIUM_REDIS_PORT=6379 \ trungdlp/podium:latest start Verify the service: curl http://localhost:8880/healthcheck WORKING Submit two equal scores: curl --request … View on GitHub Both players have 100 points. Alice arrived first, so most game designers would expect: 1. alice: 100 2. bob: 100 But that is not what the data model says. Redis sorted sets order members with equal scores lexicographically. With a reverse range, that secondary ordering is reversed too. Your "fair" tie may therefore be de
When building modern Python applications—whether scraping web pages, fetching data from external APIs, or querying databases—IO-bound operations often slow down execution. Python’s concurrent.futures module provides a high-level, elegant interface for running tasks asynchronously. In this guide, we'll break down what Futures are, why you need them, and how to use them effectively using a practical e-commerce product service. What is a Future? A Future represents an eventual result of an asynchronous operation. When you launch an expensive, long-running task concurrently, your program doesn't pause to wait for the output. Instead, it instantly gets back a Future object —a low-cost proxy or standard "claim ticket." The Future acts as a placeholder for a result that hasn't been computed yet. It keeps track of the task's execution state ( PENDING , RUNNING , CANCELLED , or FINISHED ). Once the task finishes, the Future stores the return value or any exception thrown during execution. Why are Futures Needed? In standard synchronous Python execution, calling a function blocks your main thread until that function finishes: Task 1 (2s) ──> Task 2 (3s) ──> Task 3 (1s) = 6 seconds total When dealing with IO-bound operations (like waiting for network responses or reading disks), your CPU sits completely idle during those delays. By offloading tasks into background threads or processes via Futures, your application can run multiple IO operations simultaneously: Task 1 (2s) [████████] Task 2 (3s) [████████████] Task 3 (1s) [████] ----------------------------------------- Total Time: 3 seconds (time of longest task) When Should You Use Futures? IO-Bound Workloads: Scraping multiple web pages, batch-calling microservices, querying multiple databases, or fetching images concurrently ( ThreadPoolExecutor ). CPU-Bound Parallelism: Performing heavy mathematical operations or image processing across multiple CPU cores ( ProcessPoolExecutor ). Decoupled Workflows: When you want to trigg
Designing AI Systems That Outlive Today's Models If there's one lesson this series has taught me, it's this: Don't build your application around a model. Build it around a capability. That might sound like a small distinction. It isn't. Because models change. Constantly. A few months ago everyone was talking about GPT-4. Then Claude. Then Gemini. Then DeepSeek. Then Qwen. By the time you're reading this, there's probably another model making headlines. Imagine rewriting your application every time that happens. That's not innovation. That's technical debt. One mistake I see quite often is developers tightly coupling their applications to one provider. Your business logic knows it's talking to GPT-4. Your prompts are written specifically for GPT-4. Your output parsing assumes GPT-4. Your error handling assumes GPT-4. Now imagine your company decides to switch providers. What should have been a configuration change suddenly becomes weeks of refactoring. That's avoidable. Your application shouldn't know who answered the request. It should only know that the capability it asked for was delivered. Summarize this document. Generate this code. Classify this text. Translate this paragraph. Those are capabilities. The provider is simply an implementation detail. One thing I regret not doing earlier was versioning prompts. Most developers version everything else. Source code. Database migrations. Infrastructure. Configuration. Then prompts end up looking like this: typescript id = " a8fj21 " const prompt = " You are a helpful assistant... " ; Three months later someone tweaks a sentence. Responses change. Nobody knows why. Sound familiar? Prompts deserve the same engineering discipline as code. Version them. Review them. Document why changes were made. Roll them back when needed. Prompt engineering isn't magic. It's software development. Imagine you've found a brand-new reasoning model that performs better than your current one. Do you deploy it to every user immediately? Pro
Here's the thing nobody wants to hear: we already know how to break systems where components blindly trust each other's output. We've known for twenty-five years. We just gave it a new name and forgot the lesson. Context An "AI harness" is orchestration glue. Take an LLM, wrap it with a bunch of connectors, plugins, and tool-calling scaffolding so it can actually do things (query a database, hit an API, write a file), and you've got a harness. The Dark Reading piece points out something structurally obvious once you say it out loud: these components form a chain of trust boundaries, and a lot of them don't verify what the component next to them is handing over. If that sentence gives you deja vu, it should. Deserialization bugs, SSRF via internal service calls, XML entity injection through a "trusted" upstream parser — the entire history of appsec is a history of Component A assuming Component B already did the validation. We keep rediscovering this pattern every time a new architecture pattern gets hot enough to attract production traffic before anyone's threat-modeled it. The new part isn't the trust boundary problem. The new part is that the thing sitting in the middle of the chain is a probabilistic text generator that can be talked into doing weird stuff by its own inputs, and it's now wired directly into tool execution. Hype check What's overstated: the framing that this is some novel AI-specific exploit class requiring AI-specific defenses. It's not. It's an integration security problem wearing an LLM costume. The moment you have plugins and connectors passing data between components without verification, you have the same problem you'd have gluing together any set of microservices with implicit trust. The attack surface is old news; the payload delivery mechanism (prompt-driven tool invocation) is what's new. What's understated: how fast harnesses are being shipped without anyone doing basic component-boundary threat modeling, because everyone's racing to sh
Back in February I published a post about osx-proxmox-next , a tool that builds a macOS VM on Proxmox with one command instead of an afternoon of OpenCore plist editing. About 1,500 people read it. Some of them installed it. On hardware I don't own. That's when the interesting bugs showed up. 150 commits later, here are five failures that don't appear in any macOS-on-Proxmox guide I've found, with the actual root cause for each. 1. The installer stalls at 100% CPU and nothing moves Symptom: macOS installer reaches the copy phase. CPU pegged at 100%. Disk IO and network throughput both flat zero. It sits there forever. Only on Xeon E5/E7 v2-v4 hosts. My first fix was wrong. The stall looked like a network problem, so I assumed the vmxnet3 kext was failing to load during install and swapped those hosts to e1000-82545em . Shipped it. Then issue #103 came back from someone with the actual hardware: vmxnet3 got network fine, and e1000-82545em did not attach at all. I had made it worse. The real cause is two layers down. Those chips are genuine HEDT parts with dual-socket / multi-die topology, and -cpu host leaks that topology straight through to the guest. Pair it with a MacPro7,1 SMBIOS, which macOS treats as multi-socket capable, and XNU's scheduler livelocks under heavy multithreaded IO. The installer copy phase is exactly that workload. The fix is to stop passing the host topology through: _XEON_HEDT_PATTERN = re . compile ( r " Xeon.*E[57][ -]*\d+ *v([234]) " , re . IGNORECASE ) def _xeon_hedt_cpu_model ( model_name : str ) -> str : match = _XEON_HEDT_PATTERN . search ( model_name ) if not match : return "" if match . group ( 1 ) == " 2 " : return " Haswell-noTSX,model=158,stepping=3 " return " Broadwell-noTSX,model=158 " Lesson I keep relearning: the symptom showed up at the network layer, the cause lived in CPU topology. Guessing from the symptom cost me a release. 2. The VM boots into Recovery forever Symptom: Fresh install finishes. Every subsequent boot lands b
When configuring Claude Code (or Claude-driven AI coding assistants) in your projects, structuring your instructions efficiently is key to getting accurate code generation while keeping token consumption low. Understanding when to use a single CLAUDE.md versus modular .claude/rules/ files will help keep your AI assistant sharp, focused, and predictable. The Core Hierarchy & Scope Claude Code looks for configurations across multiple levels: ├── ~/.claude/ # User / Global level (applies to all your projects) └── project-root/ ├── CLAUDE.md # Global project level (loaded into every session) ├── .claude/rules/ # Modular & scoped rules (loaded selectively) └── sub-app/ └── CLAUDE.md # Sub-directory / Monorepo scope CLAUDE.md (The Global Cheat Sheet)Think of CLAUDE.md as the main ReadMe for the AI. It provides high-level context and essential project memory. When to use CLAUDE.md:Common CLI Commands: Build, test, lint, and run scripts (npm test, docker compose up). Core Architecture: Tech stack summary, overall folder structure, and design principles. Global Rules: Non-negotiable guidelines that apply project-wide (e.g., "Strict TypeScript, no any"). Project Context: E-Commerce Web App Build & Test Commands Build: npm run build Test single file: npx jest src/components/Button.test.tsx Lint: npm run lint High-Level Guidelines All UI components must use React 19 functional syntax. Never hardcode secrets or environment variables. .claude/rules/ (Modular & Path-Scoped Rules)As projects grow, packing every guideline into CLAUDE.md bloats the prompt context and reduces overall compliance. The .claude/rules/ directory lets you create modular, topic-specific, or path-scoped rules (in .yml or .md). When to use .claude/rules/:Path-Specific Rules (globs): Guidelines that apply only to certain files (e.g., API routes vs. React components). Domain Separation: Splitting rules into dedicated files (testing.yml, security.yml, db-migrations.yml). Token Optimization: Prevent loading backen
Last week, a Baseten inference engineer who goes by @waterloo_intern published a technical blog post titled "22,580: From GPT-2 to Kimi K3, Explained." It hit 2.4 million views in days. He didn't write a press release. He wrote runnable PyTorch code — starting from GPT-2's attention block, stepping through every architectural change, explaining one problem and one cost per iteration. It's the best transformer lineage explanation I've seen. I devoured his post, then cross-checked the key claims against 5 original papers. Here's the full picture. The 22,580x Number In February 2019, OpenAI released GPT-2 — 124M parameters. Seven years later, Moonshot AI open-sourced Kimi K3 — 2.8T parameters. You could fit 22,580 GPT-2s inside one Kimi K3 . But this isn't a "throw more compute at it" story. It's a story about how we store, update, and retrieve memory . Starting Point: GPT-2 class Block ( nn . Module ): def forward ( self , x ): x = x + self . attn ( self . ln_1 ( x )) x = x + self . mlp ( self . ln_2 ( x )) return x Every time the model generates a new token, it recomputes Q, K, V projections for all historical tokens, then runs an O(N²) softmax attention. K and V from tokens 1 through N-1? Thrown away. Token N+1 arrives? Recompute everything. That's why KV Cache was invented. KV Cache: Store It, Don't Recompute Simple idea: cache the already-computed keys and values. For the next token, new Q only needs one dot product against the cached K. Problem solved — but a new one created. KV cache grows linearly with sequence length. At 1M tokens × d_model × layers, that's dozens of GB of VRAM. Every decoding step reads all of it from HBM. The bottleneck isn't compute. It's memory bandwidth. This is the key to understanding every improvement that follows. Linear Attention: Fixed-Size Memory Can we compress O(N²D) into O(ND²)? The idea: replace softmax with a feature map. # Standard softmax (must materialize N×N first) attention = softmax(QKᵀ / √d) × V # Linear attention (fold
Watching an autonomous agent run through a loop of tasks is like watching a black box try to solve a puzzle in another room. You can see the final result, but the middle part—the reasoning, the failures, and that pivotal moment where it realizes its plan was garbage—is buried in thousands of lines of unstructured logs. If you've ever deployed an agentic workflow only to check back an hour later and find it has been stuck in a high-latency loop of 'I made a mistake... let me try again' for forty minutes, you know the pain. You didn't have failure; you had expensive, silent repetition. The problem with current LLM observability is that we focus too much on the input and output (the traces) and not enough on the internal state transitions of the agent itself. We need to quantify how often an agent is actually self-correcting versus just spinning its wheels. I recently started working with a specific tool designed for this exact visibility gap: the Agent Self-Reflection & Sentiment Scanner . The Observability Gap in Agentic Loops When we talk about 'agents,' we're usually talking about a loop: Observe, Think, Act, Repeat. In a perfect world, the 'Think' step includes self-correction. If an action fails (e.g., a 403 error from an API), the agent should reflect on that failure and adjust its next move. But how do you measure if your agent is actually getting better during a session? How do you distinguish between an agent that is 'Proceeding' with confidence and one that is in a state of constant 'Correction'? You can't just look at the final success/fail status. You need to parse the execution logs for deterministic markers. Why Deterministic Matching Wins Over LLM-Based Analysis The temptation here would be to pipe your agent logs into another, even larger LLM and ask, 'Is this agent struggling?' Don't do that. It’s redundant, it’s slow, and if you're running high-volume loops, the cost will kill your margin. You've already paid for the primary reasoning engine; don't p
Disclosure: BrowserAct sponsored this piece. The BrowserAct links below are affiliate-tracked — I get...
For Job Postings please use this template Hiring: [Location], Salary:[], [Remote | Relocation], [Full Time | Contract | Part Time] and [Brief overview, what you're looking for] For Those looking for jobs please use this template Want to be Hired: [Location], Salary Expectation:[], [Remote | Relocation], [Full Time | Contract | Part Time] Resume: [Link to resume] and [Brief overview, what you're looking for] Please remember that this community is geared towards those with experience. submitted by /u/AutoModerator [link] [留言]
Hello, I'm Maneshwar. I'm building git-lrc, a Micro AI code reviewer that runs on every commit. It is...
I recently discovered you can build a fully working Flexmonster pivot table right inside a Claude...
This is a submission for DEV's Summer Bug Smash: Smash Stories powered by Sentry . A payment webhook sounds simple until a successful payment doesn't actually result in the service the customer paid for. That was one of the more interesting bugs I encountered while building The Listening Ear, an appointment and online consultation platform. The requirement was straightforward: A customer pays for a session → the application confirms the payment → the customer's appointment is booked → a Zoom meeting is created. The reality was much more complicated. Project Overview The Listening Ear connects online payments with appointment scheduling and Zoom-based consultations. The application was built with technologies including Next.js 14, TypeScript, Supabase, Prisma, PostgreSQL, Zoom, and payment-provider APIs. The payment workflow was particularly important because payment confirmation was effectively the gatekeeper for the rest of the booking experience. The intended flow looked like this: Customer │ ▼ Payment Provider │ │ webhook ▼ Next.js Webhook │ ├── Verify / interpret payment │ ├── Create Zoom meeting │ └── Create appointment record │ ▼ Customer receives access to their scheduled session The problem was that the webhook sat directly in the middle of all of these operations. Bug Fix or Performance Improvement The bug appeared when I was implementing the payment webhook that would unlock the Zoom scheduling workflow. My initial implementation listened for the payment event and checked whether the event was: if (event === 'charge.success') { Once that condition was met, the webhook immediately continued into the booking workflow. That workflow included: Reading appointment metadata from the payment event. Handling special emergency appointments. Building the Zoom meeting payload. Calling the Zoom meeting API. Creating the appointment record in the database. Returning a successful response to the payment provider. The problem was that all of these operations were effecti
Most enterprise teams know the CISA Known Exploited Vulnerabilities catalog the same way they know the weather: a headline scrolls past ("CISA adds three vulnerabilities to KEV catalog"), someone forwards it, and everyone nods. That is a waste of the single most operationally useful list in vulnerability management. The KEV is small, machine-readable, updated near-daily, and every entry on it has one property your scanner output cannot give you: a real attacker has already used it against a real network. This is a guide to the catalog itself: what it promises, what it doesn't, how the feeds are structured, how to map entries to your own estate without fooling yourself, and how to combine it with EPSS and vendor advisories into a defensible patch-ordering rule. Everything here is verified against the live feed and CISA's own pages as of late July 2026. What the KEV is, and what it is not CISA describes the KEV as the authoritative source of vulnerabilities that have been exploited in the wild . Entry is gated by three criteria , all of which must hold: The vulnerability has an assigned CVE ID. There is reliable evidence of active exploitation in the wild. There is a clear remediation action, such as a vendor-provided update. Read those criteria as exclusions and the catalog's real shape appears. No CVE assigned yet? Not in the KEV, even if exploitation is rampant. Exploitation reported but CISA's evidence bar not met? Not in the KEV. Actively exploited but no fix or mitigation exists? Not in the KEV. The catalog is a curated floor, not a census. As of the 2026.07.29 release the feed contains 1,656 entries, against an ecosystem publishing tens of thousands of CVEs per year. Absence from the KEV is not evidence of safety; presence is close to proof of danger. That asymmetry is the whole point, and it is why the correct reading of the list is "everything on here is urgent" rather than "everything urgent is on here." The distribution is also worth knowing before you buil
On a Tuesday morning in March, a chief executive asked a question that should have taken thirty seconds to answer: have we ever agreed to a liability cap below one million dollars? The answer existed. It was written down, signed, filed, and sitting on the shared drive the whole time. Finding it took three days, and not finding it in time cost forty thousand dollars. Every organization has a version of that Tuesday. The knowledge is real, it survived, and it is spread across a million files in a hundred formats, organized by whoever was closest to the filing cabinet that day. An organization knows more than anyone in it. The hard part is getting at it. Keyword search fails for a specific, fixable reason The obvious first fix is to index every word and search it. Type "liability cap," get every document containing "liability" and "cap." This fails, and it fails in ways worth naming precisely, because each failure points at what the real fix has to do. The contract does not say "liability cap." It says "limitation of liability." Two phrases, one meaning, zero shared keywords. Your search returns nothing and you conclude the document does not exist. The search bar cannot tell the difference between "we have no such contract" and "we have it, filed under different words." Matching words is not matching meaning. Search "termination" across an employee handbook and a supplier agreement and you get firing, contract expiry, and possibly a paragraph about ending a software license, ranked by nothing more meaningful than word frequency. People ask questions, not keywords. Nobody thinks in search terms. They think "have we ever agreed to a liability cap below a million?" A keyword engine has no idea that this is a question, let alone which words in it matter. What actually closes the gap The fix is to stop comparing words and start comparing meanings, which requires turning text into something you can measure distance in. An embedding model reads a passage and returns a list of
Delete a Telegram bot and https://t.me/your_deleted_bot keeps returning HTTP 200 with a page that looks completely normal. Every link checker I know of — CI actions, directory scripts, monitoring cron jobs — reports it as healthy forever. If you maintain anything that lists Telegram bots, some fraction of your list is already dead and your checks are telling you it is fine. Reproducing it Pick a username that has never existed: curl -s -o /dev/null -w "%{http_code} \n " https://t.me/nonexistent_test_bot_77712 # 200 Two hundred. No redirect, no 404, no soft-404 marker in the body that a status check would catch. Where the truth is The status code is useless here, but the Open Graph title is not. I measured four usernames — two live bots, two that do not exist: URL og:title t.me/BookClassBot (live) BookClass t.me/instanavy_bot (live) StoryViewer - anonymous instagram story viewer tool t.me/nonexistent_test_bot_77712 Telegram: Contact @nonexistent_test_bot_77712 t.me/zzz_definitely_not_a_real_bot_9182 Telegram – a new era of messaging A live bot puts its own display name in og:title . A dead one gets one of two Telegram placeholders: Telegram: Contact @<username> , or — if the username is not even syntactically valid — the generic Telegram – a new era of messaging . That is the whole signal. curl -s https://t.me/some_bot | grep -o '<meta property="og:title" content="[^"]*"' The check Standard library only, no dependencies: import re import urllib.request UA = " Mozilla/5.0 (compatible; linkcheck/1.0) " DEAD_EXACT = { " Telegram – a new era of messaging " , " Telegram " } DEAD_PREFIX = " Telegram: Contact @ " def telegram_bot_exists ( url : str ) -> bool : """ True if the bot behind a t.me URL still exists. HTTP status is not usable here: Telegram serves 200 with a placeholder page for usernames that were deleted or never existed. The Open Graph title is what actually differs. """ req = urllib . request . Request ( url , headers = { " User-Agent " : UA }) with urllib .
tinyNpm is a vs code extension that helps protect you from supply chain attacks, stale packages, and bloated code! I had been using package.json version keepers for quite some time but after the big supply chain attack i thought they would be the perfect place to add in some security. The idea is just to provide the latest package number x days old. This will help prevent most of the danger in supply in chain attacks. It will also remove the ^ if you have it so you can better control what version of a package your application is using. To be more security focused it gives general hints in the hover menu to help keep an eye on the packages you have installed. These hints include warnings for staleness, high dependency count, and number of downloads. Since all of this is something you can get through the npm api, I called it tinyNpm You can download it on the marketplace
Every idea gets run through a one-sentence test before it is allowed to count as a real idea at all Most ideas die for one of three specific reasons, not vague lack of enthusiasm An idea only earns a build slot once it has survived contact with a real, repeated problem A maybe-later list holds the rest on purpose, and I check it far less often than people assume The One-Sentence Test I Run Before Anything Becomes an Idea I get more ideas than I could ever build. That is not a boast, it is a liability if I do not manage it, because every one of those ideas feels exciting for about twenty minutes, and excitement is a terrible filter for what is actually worth my evenings. So before an idea is allowed to sit on any kind of list, it has to pass one test: can I describe the smallest useful version of it in a single sentence, with no "and" in the middle. That sounds small, but it kills more ideas than any other step in the process. "A tool that tracks my Claude usage and also shows analytics and also has a community feature" does not pass. "A tool that warns me before I hit my usage limit" passes. The first sentence is a pitch for a platform. The second sentence is a pitch for a Tuesday evening. I want the second kind, because the second kind is the one I actually finish. I did not always work this way. Early on, an idea earned space on my list the moment it sounded interesting, and my list grew into a graveyard of half-described plans that all needed a paragraph to explain. A paragraph is a warning sign now, not a feature. If I need more than one sentence to say what the smallest version does, the idea has not actually taken shape yet, it has just acquired enthusiasm, and those are different things. The test also forces honesty about scope early, before I have sunk any real time into something. An idea that needs "and" is usually two or three ideas wearing a trenchcoat, and pulling them apart at the sentence stage is far cheaper than pulling them apart three weeks into a