AI 资讯
I Spent 30 Days Comparing Startup and Enterprise AI APIs
I Spent 30 Days Comparing Startup and Enterprise AI APIs Look, I'm just a dude building a SaaS side project. Not enterprise, not Fortune 500, just me and a few friends trying to ship something useful. So when I started hitting AI API walls, I went down the rabbit hole of figuring out what the heck to do. And honestly? Most guides out there are written by people who clearly have never had to choose between buying groceries or paying for OpenAI credits. They're either too corporate ("here's our enterprise procurement guide!") or too naive ("just use the cheapest API!"). So I figured I'd write the guide I WISH existed when I started. And I'm gonna throw in some enterprise stuff too because I consulted for a bigger company last year and saw what THEY deal with. Different worlds, I tell ya. Let me break this down properly. Why I Almost Just Used DeepSeek Directly Okay so here's the thing. When I first started, I was like "DeepSeek is dirt cheap, let me just sign up there and call it a day." I mean, the pricing was wild. Like cents per million tokens. How could I lose? Then I tried to actually sign up. Chinese phone number required. WeChat Pay or Alipay only. No PayPal. No Visa. Nothing. And I get it, that's their home market, but for me sitting here in my apartment in the US? Absolute dead end. So I started looking at aggregators. Tried like four of them. Some had weird pricing. Some had models that didn't actually work. One of them straight up charged me for tokens I never used (still salty about that). Then I landed on Global API and honestly I gotta say, it just worked. Email signup, PayPal, and I could test DeepSeek AND Claude AND Qwen all with one key. That's when I realised going direct to providers is kind of a trap if you're small. Let me show you the actual problem with going direct. The "Go Direct" Trap Here's what happens when you sign up direct with various providers: Problem What Happens to You Locked to one vendor Your whole app depends on their uptime Paym
AI 资讯
Laravel Nightwatch: First-Party APM and What It Actually Replaces
Book: Decoupled PHP — Clean and Hexagonal Architecture for Applications That Outlive the Framework Also by me: Thinking in Go (2-book series) — Complete Guide to Go Programming + Hexagonal Architecture in Go My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools Me: xgabriel.com | GitHub You already run three tools that half-cover this job. Pulse gives you a live wall on a local route. Datadog runs an agent and prices on host and usage volume, so the bill scales with your infrastructure. Sentry catches the exceptions after they already hurt someone. And none of them can tell you the one thing you actually asked: the checkout request that took 900ms at 14:03 dispatched a job, that job ran a query, and the query is what timed out. Laravel Nightwatch reached general availability in 2025 as the framework's own APM, aimed straight at that gap. It is worth knowing exactly what it captures, what it charges, and where its knowledge of your app stops and yours begins. What Nightwatch actually is Two moving parts. A Composer package inside your app, and a separate agent process that ships the data. composer require laravel/nightwatch The package writes events to a local socket. The agent listens on 127.0.0.1:2407 , batches what it receives, and sends it to Nightwatch's cloud. Because the agent runs outside your request cycle, the request thread is not blocked waiting on a network call to a telemetry backend. Laravel puts the added cost at under 3ms per request ; take that as a starting figure and measure your own before you trust it. # environment token per app + environment NIGHTWATCH_TOKEN = your-env-token # start the collector (keep it running under a # process monitor: Forge daemon, Vapor, supervisor) php artisan nightwatch:agent # confirm it is alive and receiving php artisan nightwatch:status One detail that bites people: the agent has to be running for anything to arrive. In local dev you start it by hand. In product
开发者
Influencer screenings aren’t going away
For a few days, it seemed like Universal decided that there would be no advanced screenings of Christopher Nolan's The Odyssey for influencers. But on Monday, influencers sat alongside traditional critics and journalists at special showings of The Odyssey specifically for the associated press junket. Despite what it may have looked like, Universal was not […]
AI 资讯
No messages table! The data model behind my own Claude-based chatbot
This tutorial was written by Néstor Daza . This is the second article in a series about building Claudius , my own Claude-based chatbot ( Github ). The prologue made the case for building it, and for choosing MongoDB as its foundation. Open the conversations collection in Claudius’ database and you find the usual fields of a thread header but nothing else: a userId , a title , some timestamps , and so on, but no array of messages, no messages collection sitting beside it either! The text of every conversation lives somewhere else entirely, in the LangGraph checkpointer, which I wire up later in this series. This absence is a modeling decision, and how I came up with the database schema for my chatbot is the theme of this article. If you come from a relational background, you're used to modeling the data first when designing a database. For a project like this, you would start by finding the entities and normalizing them, and the final schema would come out of the data's structure: a conversations table and a messages table with a foreign key between them, because that is what the data looks like. Document modeling runs the other way. You start from how the application reads and writes, and the shape of the document follows the access patterns. Claudius never reads conversation messages without the agent's full working state wrapped around them, and that state is persisted using the LangGraph checkpointer. A separate messages table would add nothing, since the app would always have to join it back to that state on every read. The access pattern says the messages belong with the agent state, so that is where they go, and conversations are left as the lightweight header the list view actually needs. That inversion, modeling around use rather than around the data, runs through everything below. Schema-flexible is not schemaless This is the misconception lots of people often carry, and it is worth killing on the way in. A document database does not mean no schema; it mea
创业投融资
Lucid Motors’ CFO is out as its new CEO continues leadership shakeup
The company announced a new slate of executive hires meant to help turn things around, as Gravity SUV sales are not taking off as expected.
AI 资讯
AI won’t save advertising, says Digitas’ Amy Lanzi
We’ve got a special Decoder today — I had the chance to talk with Amy Lanzi, the CEO of Digitas North America, in front of a live audience at the Uber Villa at the Cannes Lions advertising festival in the South of France. I know, it’s a hard gig, but I do it for you. […]
AI 资讯
Build a Real-Time Crypto Trading Dashboard with Python, WebSockets, and React
Build a Real-Time Crypto Trading Dashboard with Python, WebSockets, and React Real-time data is the difference between catching a move and reading about it later. This tutorial walks through a minimal but complete stack: a Python WebSocket client pulling live prices, a simple signal generator, and a React frontend displaying everything. You will end up with a dashboard that shows live Binance prices, basic momentum signals, and auto-updates without polling. Why this stack Binance provides a clean WebSocket API for tickers and trades. Python handles the backend connection and lightweight analysis. React keeps the UI reactive and simple to extend. No heavy frameworks, no paid data feeds. Prerequisites Python 3.11+ Node 20+ A Binance API key (read-only is fine for prices) Step 1: Python price stream Install the client library: pip install python-binance pandas Create price_stream.py : import asyncio import json from binance import AsyncClient , BinanceSocketManager import pandas as pd from datetime import datetime async def main (): client = await AsyncClient . create () bm = BinanceSocketManager ( client ) ts = bm . trade_socket ( ' BTCUSDT ' ) async with ts as tscm : while True : res = await tscm . recv () price = float ( res [ ' p ' ]) qty = float ( res [ ' q ' ]) ts = datetime . fromtimestamp ( res [ ' T ' ] / 1000 ) print ( f " { ts } | BTCUSDT { price : . 2 f } | { qty : . 4 f } BTC " ) if __name__ == " __main__ " : asyncio . run ( main ()) Run it: python price_stream.py You should see a live feed of trades. Keep this running as your data source. Step 2: Add a simple momentum signal Extend the script to calculate a 20-trade rolling average and flag when price deviates more than 0.3%: # inside the loop, after parsing res prices . append ( price ) if len ( prices ) > 20 : prices . pop ( 0 ) avg = sum ( prices ) / len ( prices ) deviation = ( price - avg ) / avg * 100 if abs ( deviation ) > 0.3 : print ( f " ⚡ Signal: { deviation : + . 2 f } % from 20-trade avg " )
AI 资讯
How to Automate OG Image Generation for Your Blog Using a Screenshot API
Every blog post needs an OG image. Without one, your links look blank on Twitter, LinkedIn, and Slack — just a plain URL that nobody clicks. Most developers solve this by spinning up a headless browser, loading an HTML template, taking a screenshot, and uploading it somewhere. It works, but now you're maintaining a Puppeteer instance, dealing with font rendering quirks, and burning server resources on something that should be simple. There's a faster approach: design your OG images as HTML templates and let a screenshot API handle the rendering. The Idea: HTML Templates as OG Images Think of your OG image as a tiny webpage. You already know HTML and CSS. Build a 1200×630 template with your blog title, author name, maybe a gradient background — whatever fits your brand. Host it or pass it as raw HTML. Then call an API to screenshot it. Done. A basic template might look like this: <div style= "width:1200px;height:630px;display:flex;align-items:center; justify-content:center;background:linear-gradient(135deg,#1a1a2e,#16213e); font-family:Inter,sans-serif;padding:60px" > <div style= "color:#fff;text-align:center" > <h1 style= "font-size:48px;margin:0" > {{title}} </h1> <p style= "font-size:24px;color:#8892b0;margin-top:20px" > {{author}} · {{date}} </p> </div> </div> Replace the placeholders on your server, then send the resulting HTML (or a URL pointing to it) to the API. Calling the API With ScreenshotRun , a single curl request captures the rendered template as a PNG: curl -X POST "https://api.screenshotrun.com/v1/screenshot" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://yourblog.com/og-template?title=My+Post+Title", "viewport_width": 1200, "viewport_height": 630, "format": "png" }' The response gives you the image file. Save it to your CDN, set the og:image meta tag, and you're done. No browser to manage, no Chrome binary eating RAM on your CI server. Wiring It Into Your Build If you publish with a static sit
AI 资讯
Applied Creativity and Concept Generation - Brainstorming
Thomas Edison put it plainly: "To have a great idea, have a lot of them." Steve Jobs said something similar. "Creativity is just having enough dots to connect... to connect experiences and to synthesise new things." Both of them are saying the same thing. Your first idea is rarely your best one. The reason why people you call creative can come up with great ideas easily is that they have had more experiences or have thought more about their experiences than other people. So the question becomes: how do you get more ideas, faster? The Most Used Method for Applied Creativity The answer has a name. It was coined by advertising executive Alex Osborn in the 1940s. He called it brainstorming - using the brain to storm a creative problem, with each person in the room attacking the same objective. It sounds simple. Most teams think they already do it. Most of them are wrong. Real brainstorming is a structured process with rules. Break the rules, and you get something that looks like brainstorming but produces far fewer useful ideas. Why Most Brainstorming Sessions Fail Here is what kills a brainstorming session before it even starts. Someone says an idea. Someone else says, "That won't work." The room goes quiet. People stop sharing. That is it. That is the whole problem. When people fear judgment, they self-censor. They only say the safe, obvious ideas. The interesting ones, the ones that could actually lead somewhere, stay locked inside people's heads. Most teams have that one gaffer who has already decided which ideas are worth hearing before anyone has finished their sentence. Or the one who gives you the floor, listens patiently, and then quietly bins everything you said, not because it was bad, but because it was not theirs. Both types do the same damage. The room reads it. People stop sharing. And just like that, the best idea in the session never gets spoken. The goal of brainstorming is to get more ideas. That means the number one rule is: defer judgment . The Rule
AI 资讯
Observability Practices: A Hands-On Guide with Prometheus and Grafana
Introduction Modern software systems are distributed, complex, and constantly changing. When something breaks in production, you need answers fast. That's where observability comes in. Observability is the ability to understand the internal state of a system purely from its external outputs — without needing to redeploy, add debug code, or guess. It goes beyond traditional monitoring, which only tells you whether something is wrong. Observability tells you why it's wrong, where it started, and how it's spreading. In this article, we'll explore the three pillars of observability, set up a real Node.js API instrumented with Prometheus and Grafana , and walk through how to detect and diagnose a real-world issue using the data we collect. The Three Pillars of Observability 1. Logs Logs are discrete, timestamped records of events that happened in your system. They're the most familiar form of observability — every developer has done console.log debugging at some point. Example: [2026-07-02T10:34:21Z] INFO User 4821 logged in from IP 192.168.1.10 [2026-07-02T10:34:25Z] ERROR Failed to process payment for order #9932: timeout Logs are great for capturing specific events, errors, and context. But they can become expensive at scale and hard to query across millions of lines. 2. Metrics Metrics are numeric measurements collected over time. Unlike logs, they're aggregated and efficient to store and query. Common examples: HTTP request count per minute p95 response latency CPU and memory usage Error rate per endpoint Metrics are the backbone of dashboards and alerts. 3. Traces Traces follow a single request as it travels across multiple services. In a microservices architecture, a user request might touch 5–10 services. A trace shows you exactly where time was spent and where failures occurred. Tools like Jaeger , Zipkin , and OpenTelemetry handle distributed tracing. Why Prometheus and Grafana? There are many observability platforms out there: Datadog, New Relic, Dynatrace, Az
AI 资讯
How to Automate Content Research Using Python and APIs (Step-by-Step)
I used to spend ten hours every week doing content research manually. Checking competitor blogs. Scanning Reddit threads. Copying and pasting search results into a spreadsheet. Trying to spot patterns in an ocean of unstructured text. It was exhausting, slow, and completely unnecessary. Once I learned to automate this with Python and a few affordable APIs, I cut that ten-hour grind down to under thirty minutes. Here is the exact system I built, what it costs, and how you can replicate it yourself. The Quick Answer To automate content research with Python, combine a search API like Serper to pull structured Google search data, BeautifulSoup or requests-html to parse page content, and an LLM API like Gemini to synthesize insights into actionable content briefs. Connect these three components in a sequential Python pipeline and you have a fully automated research agent that runs in minutes instead of hours. What I Actually Built I needed a system that could do three things automatically: First, find what real people are asking about any topic across Reddit, Quora, and Google search. Second, identify what my top competitors have written about that topic and where the gaps are. Third, summarize everything into a clean content brief I can use to write or generate an article. I built this using Python with three core components: the Serper API for search data, BeautifulSoup for page parsing, and the Google Gemini API for synthesis. Total monthly cost: about twelve dollars. I document the full working version of this system — including the Flask web interface and WordPress publishing integration — at https://zerofilterdiary.com Step-by-Step Build Guide Step 1: Install the Required Libraries pip install requests beautifulsoup4 python-dotenv google-generativeai Step 2: Set Up Your API Keys Create a .env file in your project root: SERPER_API_KEY=your_serper_key_here GEMINI_API_KEY=your_gemini_key_here Step 3: Search for Real Discussions Using Serper API import requests import
开发者
How to Test On-Demand Logistics Apps: From Booking to Doorstep Deliver
Testing a food delivery app is hard. Testing an on-demand logistics app is harder. Food delivery has...
AI 资讯
The Markdown File That Beat a $50M Vector Database: Separating Storage and Search in Agent Memory
In the rush to build AI agents, we defaulted to complex vector databases. But high-traffic platforms are converging on a simpler, more robust foundation: plain files. Most long-term agent memory setups are massively over-engineered. When developers start building LLM applications, the default prescription is almost always: "Spin up a managed vector database and build a RAG pipeline." But if you look at the highest-traffic production agent platforms (like Claude Code, Manus, and OpenClaw), a quieter trend has emerged. They are bypassing the enterprise embeddings store and using plain markdown files as their primary memory substrate. This is not a regression to simplicity. Done well, it is a stronger engineering foundation because files are inspectable, diffable, portable, and git-native. But a folder of plain text notes with no structure is just a slow, poorly indexing database. To make a file-first architecture work at scale, you must follow a fundamental system design principle: separate storage from search . The Core Invariant: Storage vs. Search The single highest-leverage decision you can make in agent memory design is treating your storage layer and search indexes as completely separate systems. Storage (Canonical Source of Truth): Versioned, human-readable files (Markdown + YAML frontmatter). Search (Derived Index): Derived search structures (vector databases, full-text BM25 indexes, entity graphs, keyword indexes). In this architecture, every search index is treated as a disposable artifact. You can delete your vector embeddings database or rebuild your entity graph at any time, with zero loss of underlying memory. This buys you three advantages: Auditability for free: By storing memories in text files, you can version-control them using Git. Every memory update, supersession, or correction is diffable, attributable, and reversible without any custom database versioning logic. Algorithmic freedom: Swap your embedding models, adjust your chunking strategies, o
科技前沿
Even Honda is pivoting to data centers
Honda wants in on the lucrative energy storage market. This week it began producing batteries destined for data centers, not driveways.
AI 资讯
Motorola Phones Now Have a Built-In Travel eSIM for Mobile Data Outside the US
Available in select markets thanks to a partnership with Gigs, Motorola phone owners have one less hurdle to clear when signing up for a data-only eSIM before traveling abroad.
AI 资讯
Stop Letting AI Agents Raw-Dog Your Filesystem: Building SafeMCP
We need to have a serious talk about the Model Context Protocol. Everyone is losing their minds over "vibe coding" right now. You plug an MCP server into Cursor, Claude Code, or VS Code, tell the AI to fix a bug across three directories, and go grab a coffee while it spins up local servers, reads files, and executes terminal commands. It feels like absolute magic. But honestly? It's also completely terrifying. Maybe I’m just paranoid, but it seems like we’ve collectively skipped the part where we ask ourselves if giving a statistical text-prediction engine raw, unvetted access to our local machines is a good idea. Some security folks are already warning that we’re walking directly into a massive remote code execution crisis. Think about it. Most MCP servers run as local subprocesses. They inherit your exact user permissions. If you run your editor as an admin or with access to sensitive environment variables, so does the AI. And the real issue isn't that the AI will spontaneously turn evil. The issue is prompt injection. The Security Void in the Hype I spent some time looking through public MCP servers on GitHub recently, and the sheer lack of input validation is wild. Because developers are rushing to build cool tools, basic security hygiene has completely lagged behind. If an AI agent reads an untrusted string—like a malicious comment in a GitHub issue, an automated email, or a dirty record inside a database—it can easily be manipulated into executing an injection payload. The model doesn't know the difference between your system instructions and the data it's processing. It treats them exactly the same. What happens when a prompt injection tricks a standard filesystem MCP tool into looking for a file named ../../../../../../etc/passwd or pulling your private AWS keys? The tool just does it. It’s a classic path traversal vulnerability, except instead of a malicious hacker typing it into a web form, an automated agent is doing it because a piece of text told it to.
AI 资讯
Proxying RabbitMQ Management UI Through Nginx (Fixing the %2F Problem)
The Problem When you put RabbitMQ's Management UI behind an nginx reverse proxy under a sub-path like /rabbitmq/ , queue detail pages and many API calls break silently. The root cause: nginx normalizes the request URI before proxying. It decodes %2F (the URL-encoded forward slash) into a literal / . RabbitMQ's Management API uses %2F to represent the default virtual host ( / ) in API paths: GET /api/queues/%2F/my-queue When nginx decodes it: GET /api/queues///my-queue ← broken What Doesn't Work The common advice of using merge_slashes off or a rewrite directive doesn't fully solve this because nginx still normalizes $uri before forwarding. The Fix Use $request_uri inside an if block. Unlike $uri , $request_uri holds the raw, undecoded URI exactly as the client sent it — nginx never touches it. nginx # RabbitMQ: API paths — use $request_uri to preserve %2F (never decoded by nginx) location ~* ^/rabbitmq/api/ { if ($request_uri ~* "^/rabbitmq/(.*)") { proxy_pass http://rabbitmq:15672/$1; } proxy_buffering off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; } # RabbitMQ: general UI (JS, CSS, static assets, non-API pages) location ~* ^/rabbitmq/ { rewrite ^/rabbitmq/(.*)$ /$1 break; proxy_pass http://rabbitmq:15672; proxy_buffering off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; }
AI 资讯
Bikin "Otak" AI Agent Bisa Diedit di Obsidian: Panduan Sinkronisasi Dua Arah untuk Pemula
Pernah kepikiran, "Sebenarnya AI agent saya inget apa aja sih soal saya?" Kalau iya, tulisan ini buat kamu. Masalahnya: Memori AI Itu Kotak Hitam Kalau kamu pakai AI agent yang punya memori jangka panjang (persistent memory), kamu mungkin pernah ngerasa gak nyaman karena beberapa hal ini: Gak tahu persis apa yang diingat AI tentang kamu Gak tahu file-nya disimpan di mana Gak bisa edit memori itu tanpa ngetik perintah lewat chat Takut kalau file memorinya rusak, semua informasi hilang begitu saja Studi kasus di tulisan ini pakai Hermes Agent , agent open-source besutan Nous Research. Sebagai konteks buat yang belum familiar: Hermes Agent adalah agent AI open-source yang berjalan sebagai proses (daemon) mandiri di server milikmu sendiri, mengumpulkan memori lintas sesi, menjalankan tugas terjadwal, terhubung ke belasan platform pesan, dan menulis skill-nya sendiri dari pengalaman. Framework berlisensi MIT ini dirilis Februari 2026 dan dengan cepat menarik perhatian komunitas open-source AI. Hermes menyimpan memorinya di dua file utama: USER.md (profil tentang kamu) dan MEMORY.md (catatan agent soal lingkungan kerja, kebiasaan, dan pelajaran yang dipetik), plus satu file lagi SOUL.md untuk "kepribadian" si agent. Semuanya disimpan dalam format teks polos yang dipisah pakai karakter § , seperti ini: Preferensimu: komunikasi singkat dan langsung § Namamu Budi, awal 30-an, tinggal di Surabaya § Penggemar PKM / Building a Second Brain Format ini fungsional, tapi ada beberapa kekurangan: Susah diedit langsung karena bukan format yang ramah manusia Gak ada riwayat versi — sekali salah edit, informasi bisa hilang selamanya Gak ada tampilan visual — susah lihat semua catatan sekaligus Gak ada antarmuka grafis — harus lewat chat agent atau edit file mentah Solusinya: pindahkan memori itu ke Obsidian , aplikasi catatan berbasis markdown yang mendukung riwayat versi lewat git dan bisa diedit bebas. Arsitektur Sistemnya Sistem sinkronisasi ini punya empat lapisan: ┌───────────────
AI 资讯
AI Metrics Baseline: Prove Your Feature Works Before Scaling It
An AI feature can feel impressive and still be a bad product decision. The demo is fast. The answer sounds useful. The team is excited. Then usage grows and nobody can answer the basic questions: Is it accurate enough? Is it saving time? Which customers trust it? Why did costs spike? Should we scale it, fix it, or kill it? That is the trap an AI metrics baseline prevents. A baseline is not a dashboard full of vanity charts. It is a small set of before-and-after measurements that tells you whether an AI workflow is getting better, getting worse, or merely getting more expensive. Why AI features fail without a baseline Most software teams already track uptime, errors, and conversion. AI features need those too, but they also need new signals because model behavior is probabilistic. A normal API either returns the expected response or throws an error. An AI workflow can return: a fluent answer that is wrong a correct answer with missing evidence a useful answer that costs too much a slow answer that users abandon a safe answer that refuses too often a cheap answer that hurts trust a high-rated answer that does not improve the business workflow Without a baseline, every production discussion becomes opinion-driven: "The model seems better." "Users like it." "The new prompt reduced hallucinations." "The expensive model is worth it." Maybe. Maybe not. The baseline turns those claims into measurable comparisons. What an AI metrics baseline is An AI metrics baseline is the starting measurement for the workflow before you optimize or scale it. It answers five questions: What does the workflow cost today? How good are the outputs today? How fast and reliable is the experience today? Do users adopt and reuse it? Does it improve the real task it claims to improve? You do not need 80 metrics on day one. You need a small set of metrics that match the feature's risk and purpose. For example: Feature Useful baseline Support answer bot resolution rate, citation quality, escalation r
AI 资讯
The Token Bucket Algorithm: Build Server-Side API Rate Limiting in ~40 Lines
The Token Bucket Algorithm: Server-Side API Rate Limiting in ~40 Lines Plenty of tutorials teach you how to survive someone else's rate limit with retries and backoff. Far fewer show you how to build one. If you run an API, you need rate limiting on your side too — to protect your database from a runaway client, keep one noisy tenant from starving everyone else, and give abusive traffic a polite 429 instead of a melted server. The cleanest algorithm for the job is the token bucket . Let's implement it from scratch, then make it production-ready. How token bucket works Picture a bucket that holds up to capacity tokens. Every request removes one token. The bucket refills at a steady refillRate (tokens per second), up to its cap. If a request arrives and the bucket is empty, it's rejected. This gives you two useful properties at once: A sustained rate — the long-run average, set by refillRate . A burst allowance — clients can spend the whole bucket at once, set by capacity . That burst tolerance is why token bucket feels fair. A user who's been quiet for a minute can fire off a batch of requests without being punished for it. A minimal implementation Here's a self-contained bucket in JavaScript. No dependencies, no timers — we compute refill lazily based on elapsed time, which is both simpler and more accurate than a background interval. class TokenBucket { constructor ( capacity , refillRatePerSec ) { this . capacity = capacity ; this . refillRate = refillRatePerSec ; this . tokens = capacity ; this . lastRefill = Date . now (); } _refill () { const now = Date . now (); const elapsedSec = ( now - this . lastRefill ) / 1000 ; this . tokens = Math . min ( this . capacity , this . tokens + elapsedSec * this . refillRate ); this . lastRefill = now ; } take ( cost = 1 ) { this . _refill (); if ( this . tokens >= cost ) { this . tokens -= cost ; return { ok : true , remaining : Math . floor ( this . tokens ) }; } const deficit = cost - this . tokens ; const retryAfter = Mat