AI 资讯
Integrating Lambda Durable Functions into a Step Functions Workflow
At re:Invent 2025, AWS announced Lambda Durable Functions . The feature introduces a checkpoint/replay mechanism that allows Lambda executions to run for up to one year, automatically recovering from interruptions by replaying from the last checkpoint. Lambda's 15-minute timeout is not a bug or a limitation to work around. It is a deliberate design choice that encourages keeping functions simple and focused, and in most cases it does its job well. When a function needs more time, the usual approach is fanout : split the work into smaller Lambdas, orchestrate them, move on. I have done it many times and it works perfectly fine. But a few days ago I was developing a new Lambda function for a pipeline orchestrated by Step Functions, and the execution time exceeded 15 minutes. I could have done the usual split, but durable functions had just come out and I wanted to try them. At first glance, durable functions can look like a replacement for Step Functions. Both services manage multi-step workflows , both offer checkpointing and automatic recovery , and both let you coordinate complex operations. For certain use cases, that might actually be the case: if your entire workflow lives inside a single Lambda, durable functions can handle everything on their own without an external orchestrator. But the AWS documentation actually suggests using them together. The "Hybrid architectures" section says it explicitly: many applications benefit from combining the two services, using durable functions for application-level logic within Lambda and Step Functions to coordinate the high-level workflow across multiple AWS services. My case fit that description, and more than a perfect architectural match, I wanted to learn how the two services actually work together and form my own opinion on when the hybrid approach makes sense. I figured integrating the two would be a small change. It was my first time working with the durable execution SDK, and since the code I write is mostly infras
AI 资讯
Running a 120-site uptime monitor for $0/month on Cloudflare's free tier
I built a tool that answers one question: when a website won't load, is it your connection or the site? It runs two checks in parallel — measures your own line in the browser (latency + a 1 MiB download), and probes the target from Cloudflare's edge — then returns one of four verdicts: it's not you, it's you, it's both, or all clear. Demo: https://itsnotyou.site The interesting part isn't the tool, it's that the whole thing — app, ~120 monitored sites with 24h history, SSR status pages, share cards, outage alerts — runs for $0/month plus domains. The one thing that wanted to cost money Everything fit the Workers free plan except a background monitor probing ~120 sites on a tight cadence. As a Worker cron that's ~120 subrequests/run and, done naively, thousands of KV writes/day — which pushes you onto Workers Paid. The real ceiling is KV: 1,000 writes/day. So I split it. The user-facing test stays on Cloudflare — the edge probe still measures from the colo nearest the user, which is the point of edge. But the background sweep moved to a cheap VPS I already had: it probes the roster on a systemd timer and pushes results back into KV over the REST API. Staying under 1,000 KV writes/day One KV key, not key-per-site. All ~120 statuses live in a single blob. Key-per-site at sweep cadence would be millions of writes/month; a single blob is one write per sweep. Widen the cadence. I started at 2 min = 720 writes/day. Cloudflare emailed that I'd hit 50% of the daily limit (the sweep wasn't the only writer). I went to 3 min = 480/day, leaving headroom for share cards and the notify list. Move the hot counter off KV. The anonymous "tests today" counter was the sneaky risk — a traffic spike could exhaust the write budget and stall the status sweep, the one thing you can't let happen. It went to Analytics Engine instead (free, uncapped, separate budget). Now no amount of user traffic can starve the monitor. Reader and writer share code so their rules never drift: the streak/histo
AI 资讯
Why I Chose Neon (dev.to Database Partner) for My AI Routing Platform
When Neon became the official database partner of DEV Community, I was already a user. But the partnership made me look closer at why I chose Neon — and whether those reasons apply to other AI developers. They do. Here's why Neon is the ideal database for AI applications in 2026. The Problem: AI Apps Have Unique Database Needs AI applications have database requirements that traditional web apps don't: High write volume — every AI request generates logs, metrics, and cost data Variable load — traffic spikes when a model goes viral, then drops to zero Schema evolution — you're constantly adding models, routing rules, and analytics tables Dev/prod parity — you need to test routing changes against real production data Edge compatibility — AI APIs need sub-100ms response times globally Traditional PostgreSQL (RDS, Aurora) struggles with all five. Neon was built for them. Feature 1: Database Branching (The Game-Changer) This is Neon's killer feature. It works like git branch but for your entire database: # Create a branch from production neon branches create --parent main --name test-deepseek-v31 # Get a connection string for the branch neon connection-string test-deepseek-v31 # → postgresql://...@ep-test-deepseek...neon.tech/neondb # Run migrations on the branch npx prisma db push --url $BRANCH_URL # Test your new routing algorithm against REAL data # (the branch is a copy-on-write clone of production) # When tests pass, merge neon branches merge test-deepseek-v31 Why This Matters for AI Apps When I added DeepSeek V3.1 to my model pool, I needed to test: Would the new model break existing routing rules? Would the cost calculations be correct? Would the latency meet my SLA? With traditional PostgreSQL, testing against real data meant either: Copying production to a staging DB (hours, $$) Testing with synthetic data (unreliable) With Neon branching, I branched, tested in 30 seconds, and merged. Zero downtime, zero risk. Feature 2: Scale-to-Zero (Cost Optimization) Neon's c
AI 资讯
WebMCP Runs In Chrome. My 400 Daily Tool Calls Don't.
WebMCP Runs In Chrome. My 400 Daily Tool Calls Don't. Google I/O 2026 shipped WebMCP and half the AI Twitter timeline is calling it "the new MCP standard." It isn't. It's a browser-scoped protocol that solves a completely different problem than the MCP servers currently running on your VPS at 3 AM. Here's the boundary Google buried in the docs, and how to decide which side of it your agent belongs on. What WebMCP actually is (and isn't) WebMCP is a browser-scoped tool protocol. It exposes tools to an agent from inside a Chrome tab — the tools live in the page, auth is the user's active session, and the runtime is the browser itself. That's the entire surface area. When Google says "agentic web," they mean an agent that operates inside a tab the user already has open, using the cookies and OAuth tokens already loaded. That's a legitimate and useful pattern: Booking flows — agent fills a multi-step form on a site the user is signed into Dashboards — agent pulls a chart, exports it, drops it into a doc In-app copilots — SaaS product ships tools its own users' agent can call Form fillers and page-scoped assistants What WebMCP is not : a replacement for the stdio and HTTP MCP servers running headless on your machine or VPS. Different runtime, different auth model, different lifecycle. Calling it "the new MCP" is like calling a service worker "the new backend." Same protocol family, entirely different deployment target. The split that actually matters There's exactly one question you need to answer to pick correctly: Is a human looking at a screen when the agent runs? If yes → WebMCP is on the table. If no → you need a real server-side MCP. That's it. Everything else is retweet noise. Dimension WebMCP stdio / HTTP MCP Runtime Chrome tab Your process (local, VPS, container) Auth User's browser session Your API keys / OAuth tokens Trigger User action in the page cron, webhook, queue, schedule Lifecycle While tab is open 24/7 headless Credentials scope Whatever the user is l
AI 资讯
HTTP Server — Request Lifecycle
Request lifecycle: một HTTP request đi qua đâu, và vì sao "quên gọi next()" làm request treo cho tới khi socket timeout Một request tới một Express hay Fastify server không phải là "gọi handler rồi trả về response". Nó là một chuỗi các bước theo thứ tự cố định: parse HTTP, chạy qua middleware/hook, match route, gọi handler, serialize, gửi response, đóng. Nếu bất kỳ bước nào không chuyển tiếp — Express không gọi next() , Fastify hook không reply.send() hay không return — request treo cho tới khi client hoặc server timeout đóng socket. Đây là loại lỗi không ném exception, không xuất hiện trong error log, chỉ hiện ra qua p99 latency phình lên và số socket ở trạng thái ESTABLISHED tăng dần. Hiểu chính xác lifecycle này là điều kiện tiên quyết để debug những request "biến mất" và để đặt middleware đúng thứ tự. Cơ chế hoạt động Bước dưới cùng giống nhau ở cả hai framework: Node core http.Server nhận TCP connection, parse HTTP request line + headers, phát event request với hai object IncomingMessage (req) và ServerResponse (res). Điểm khác nhau là những gì framework làm giữa lúc nhận request và lúc response ra khỏi socket. Express dựng một chuỗi middleware qua Router . Mỗi lần app.use(fn) hay app.get(path, fn) được gọi, Express bọc fn vào một Layer với path regex (thông qua path-to-regexp ) rồi push vào một stack. Khi request đến, Router.handle duyệt stack tuần tự: với mỗi layer, nếu path match, gọi fn(req, res, next) . next() là closure trỏ vào layer kế tiếp; chỉ khi nó được gọi thì layer sau mới chạy. Error handler được nhận diện bằng arity — hàm 4 tham số (err, req, res, next) — và chỉ được duyệt tới khi next(err) được gọi: import express from ' express ' const app = express () app . use ( express . json ({ limit : ' 1mb ' })) // 1. parse body app . use (( req , _res , next ) => { // 2. request id req . id = crypto . randomUUID () next () }) app . use (( req , _res , next ) => { // 3. auth const token = req . headers . authorization if ( ! token ) return next ( new Erro
AI 资讯
Your SQS Queue Is Redelivering Messages Your Lambda Is Still Processing
Your order-processing Lambda starts sending duplicate confirmation emails. Not always — maybe one order in twenty. CloudWatch shows more invocations than messages published. The function code hasn't changed in weeks. What changed is that someone added a fraud check that pushed processing time from 25 seconds to around 45, and your SQS queue is still running the default 30-second visibility timeout. That combination is the whole bug. When a Lambda pulls a message from SQS, the message isn't deleted — it's hidden for the duration of the visibility timeout. If the function is still working when that window closes, SQS assumes the consumer died and hands the same message to another invocation. Now two Lambdas are processing the same order, both will "succeed," and both will send the email. Nothing errors. Nothing retries. There is no log line that says "this message was delivered twice because your timeouts are misconfigured." Infrawise ( npm ) flags this exact mismatch as a high-severity finding before it costs you an afternoon of staring at idempotency-free handler code. This post walks through why the bug is so hard to see, how the detection works, and how to keep an AI assistant from reintroducing it. Why you never catch this one yourself Three things make this misconfiguration nearly invisible: It passes every test. In local tests and staging, your handler processes a synthetic message in two seconds. The 30-second visibility window never comes close to expiring. The bug only exists under production conditions — real payload sizes, real downstream latency, cold starts stacking on top of slow dependencies. The defaults set the trap. SQS queues default to a 30-second visibility timeout. Lambda functions routinely get their timeout bumped to 60, 120, or 900 seconds as they grow. Nobody bumps the queue at the same time, because the two settings live in different consoles, different IaC resources, and usually different pull requests. The failure signature points elsewhe
AI 资讯
How I Built an Ultra-Fast Bilingual Dictionary Handling 293,000+ Words on the Edge
Every developer has that one project. The passion build that sits in the back of your mind for months—or even years—before you finally sit down, crack your knuckles, and make it a reality. For me, that project was building a modern, open-access bilingual digital lexicon bridging English and Assamese: AssameseDictionary.org . While it started as a personal milestone dream, it quickly turned into a massive data engineering and architecture challenge. Here is how I tackled parsing a massive vocabulary database and serving it globally with near-zero latency. 🏗️ The Core Challenge: Scale vs. Speed A dictionary isn't like a standard SaaS app or landing page. It lives and dies by its database depth. To make this a truly definitive tool, I compiled, cleaned, and programmatically validated an extensive vocabulary index mapping over 293,000 words . The dataset doesn't just hold simple translations; it maps complex bidirectional lookups, phonetic transliterations, advanced English definitions, context usage examples, and cross-linked synonym tokens. If I threw this massive dataset into a traditional relational database hooked up to a standard server setup, I ran into immediate roadblocks: Latency: Heavy search queries on a dataset this size can cause noticeable lag. Cost/Overhead: Maintaining and scaling database servers for unpredictable public traffic gets expensive fast. I wanted the search utility to snap back instantly. To achieve that, I had to ditch traditional server paradigms entirely. ⚡ The Architecture: Serverless Edge Caching To keep things ultra-lightweight, highly cost-effective, and blazing fast, I built the platform around an edge-computing topology: The Runtime: I offloaded the backend logic entirely to Cloudflare Workers . Instead of routing traffic to a centralized origin server, queries are intercepted and executed at serverless edge locations physically closest to the user. The Data Layer: Instead of an active SQL database bottleneck, I mapped the data mat
AI 资讯
A/B Testing at Warp Speed: How Cloudflare Workers Revolutionize HTML Experiments
Let's be honest—traditional A/B testing is broken. If you've ever implemented client-side testing, you know the drill. Your users load the page, wait for JavaScript to execute, and then—flicker—the content changes. It's jarring. It hurts your Core Web Vitals. And worst of all, your experiments might be measuring user frustration instead of genuine engagement. But what if you could run A/B tests with zero flicker? What if you could modify your HTML before it even reaches the browser? That's exactly what Cloudflare Workers make possible . The Server-Side Advantage A/B testing at the edge means making decisions about which variant a user sees before any HTML is sent to their browser . Instead of: Load the page Execute JavaScript Flicker Apply the variant Track the result You get: Decision made at the edge Correct HTML streamed immediately Zero flicker Better performance Companies like Ninetailed are already using Cloudflare Workers to achieve 2-3x cost savings compared to traditional serverless platforms, all while delivering personalized experiences with minimal latency . How It Actually Works The concept is surprisingly elegant. Your Cloudflare Worker intercepts incoming requests, checks for a cookie to maintain user consistency, and routes users to the appropriate variant . Here's a simplified version that's production-ready: javascript const NAME = "myExampleWorkersABTest"; export default { async fetch(req) { const url = new URL(req.url); // Determine which group this user is in const cookie = req.headers.get("cookie"); if (cookie && cookie.includes(`${NAME}=control`)) { url.pathname = "/control" + url.pathname; } else if (cookie && cookie.includes(`${NAME}=test`)) { url.pathname = "/test" + url.pathname; } else { // New user—randomly assign them (50/50 split) const group = Math.random() < 0.5 ? "test" : "control"; url.pathname = `/${group}` + url.pathname; // Fetch and modify the response to set a cookie let res = await fetch(url); res = new Response(res.body, res
开发者
Nano Banana 2 Lite with MCP, and Antigravity CLI
This article covers the MCP setup and configuration for using Google Nano Banana 2 Lite and...
AI 资讯
My "serverless" database was billing me like it never slept.
My "serverless" database was billing me like it never slept. Neon has this great feature called scale-to-zero. Your Postgres compute suspends when it's idle, so you only pay for the queries you actually run. For a pre-revenue product, that should cost a few cents a month. Mine ran 24/7. The compute never once scaled to zero. The culprit wasn't my app logic. It was my database driver. I was using postgres-js, which holds a persistent connection open to the database. From Neon's side, an open connection looks like activity, so it never suspended. It just stayed awake and kept quietly billing me. The fix was basically one conceptual change: switch to @neondatabase/serverless, the HTTP driver. Instead of a long-lived connection, every query becomes a stateless one-shot HTTP request. The query fires, the connection closes, and the compute is free to suspend. Scale-to-zero finally worked. The lesson I keep relearning as a solo founder: "serverless" is a property of your whole stack, not a checkbox on one service. One persistent connection upstream and the whole cost model breaks.
AI 资讯
I built an AWS access recertification engine that actually enforces the decision
The access you revoked in your last review is probably still live. I know how that sounds, but it is how most access recertification actually works. A tool generates a list, an owner clicks approve or revoke, the cycle gets marked complete, and then nothing touches the real resources. The review produces a record. The permissions stay exactly where they were. You attested to a state that was never made true. That gap bothered me for a long time, so I built something to close it and open-sourced it on AWS's aws-samples org. It is called VIGIL. The core idea A normal review answers one question: should this access still exist? The owner says no, a ticket gets filed, and maybe someone actions it next quarter. Between the decision and the change, the risk just sits there. I wanted the decision and the change to be the same step. So VIGIL does four things: It discovers resources by their owner tag and works out who actually has access to each one. It asks the owner to keep, trim, or remove that access. It applies that decision on the live resource. It records what happened in a way you can later prove. The part I care about most: scoped enforcement The lazy way to revoke someone's access to one bucket is to detach their policies. That nukes their access to everything, and it is how you cause an incident while trying to improve security. VIGIL never does that. If the access came from a bucket policy, it removes just that principal, or just the specific actions, from that bucket's policy. If the access came from the principal's own IAM policy, it adds a resource-scoped explicit Deny instead of touching shared policy, so nothing else the principal can do is affected. In practice it can remove only s3:PutObject for one principal on one bucket and leave everything else alone. If a change cannot be made safely and narrowly, it raises a ticket instead of guessing. I would rather it do nothing than do something broad. Making enforcement durable Enforcement is not a synchronous c
开发者
BurnAfterRead – E2E encrypted self-destructing drops on Cloudflare Workers
I built a zero-knowledge secret sharing tool. Text and files are encrypted in the browser with AES-GCM 256 before upload - the server only ever sees ciphertext. The decryption key lives exclusively in the URL fragment (#k=...). URL fragments are never sent in HTTP requests (RFC 9110 §4.2.3), so Cloudflare Workers, D1, and R2 never see it - even in logs. A few things I tried to do right: Single-use by default: Durable Objects handle atomic read→decrement→delete with blockConcurrencyWhile, no race conditions on concurrent requests Paranoid mode: returns not_found instead of expired/burned, no timing oracle Revoke endpoint: delete a drop before it's read using a SHA-256'd token with constant-time comparison CLI: burnafter send / burnafter receive - full E2E from terminal, key never touches a browser - /security page with a live in-browser AES-GCM demo and a manual Node.js decryption snippet so you can verify without trusting me Stack: Cloudflare Workers + D1 + R2 + Durable Objects. No third-party crypto libs. Live: https://burnafterread.casablanque.com Source: https://github.com/casablanque-code/burnafterread Verify: https://burnafterread.casablanque.com/security
AI 资讯
AWS Lambda MicroVMs: I Tested the New Stateful Serverless Primitive
What just happened On June 22, 2026, AWS quietly launched Lambda MicroVMs. Not a Lambda feature update. A new compute primitive sitting between Lambda Functions (stateless, 15-min max) and EC2 (full VM, you manage everything). Each MicroVM is an isolated Firecracker VM with its own HTTPS endpoint, running your code from a pre-built snapshot. Stateful. Up to 8 hours. Suspend when idle, resume on demand. I tested it the same week. Here's what I found. The test setup A minimal Python HTTP server packaged as a Dockerfile: from http.server import HTTPServer , BaseHTTPRequestHandler import json , time , os class Handler ( BaseHTTPRequestHandler ): start_time = time . time () request_count = 0 def do_GET ( self ): Handler . request_count += 1 body = json . dumps ({ " message " : " Hello from Lambda MicroVM! " , " uptime_seconds " : round ( time . time () - Handler . start_time , 2 ), " requests_served " : Handler . request_count , " pid " : os . getpid () }) self . send_response ( 200 ) self . send_header ( " Content-Type " , " application/json " ) self . end_headers () self . wfile . write ( body . encode ()) HTTPServer (( " 0.0.0.0 " , 8080 ), Handler ). serve_forever () The Dockerfile: FROM public.ecr.aws/lambda/microvms:al2023-minimal RUN dnf install -y python3 && dnf clean all WORKDIR /app COPY app.py . EXPOSE 8080 CMD ["python3", "app.py"] How it works Three steps: Zip code + Dockerfile → upload to S3 create-microvm-image builds the container, starts the app, takes a Firecracker snapshot of memory and disk run-microvm launches from that snapshot Every launch resumes from the pre-initialized state. No cold boot. Your app is already running the moment the MicroVM starts. aws lambda-microvms create-microvm-image \ --name hello-microvm-test \ --code-artifact "uri=s3://my-bucket/artifact.zip" \ --base-image-arn arn:aws:lambda:us-east-1:aws:microvm-image:al2023-1 \ --build-role-arn arn:aws:iam::123456789:role/MicroVMBuildRole Image build took about 3 minutes. Once done: aw
AI 资讯
You don't need Vercel Pro. You need your stack to sleep.
TL;DR for vibe coders: Shipped an app with Cursor, Claude Code, or v0 and got a scary Vercel or Neon bill? You probably don't need a bigger plan. You need a few fixes. Not technical? Copy the agent-rules folder from the companion repo into your project and tell your AI editor "apply these cost rules." That's the whole job. You don't need Vercel Pro. You don't need to "Launch" on Neon. A lot of the time you need the opposite of an upgrade. You need your stack to go to sleep. Here's the moment that started this. A Neon bill landed, across three small Next.js apps running on Vercel with a Neon Postgres database, and the breakdown was lopsided in a way that gave the whole game away. $32.65 of it was compute. Storage was 5 cents. History and data transfer were zero. The meter said 308 hours of compute time in about three weeks, which is a database awake for roughly fifteen hours a day, every day. The instinct when a bill climbs is "I must be getting traffic, time for a bigger plan." So before doing that, I opened Google Analytics. Zero users in the last 30 minutes. Meanwhile the database compute was pinned active, and had been more or less around the clock. So this was never a storage problem or a traffic problem. Almost the entire bill was one thing: paying for a database to stay awake doing nothing. Both of those things were true at the same time, and here's the part I'll say up front so nobody has to guess: I didn't hand-write the mistakes that caused this. AI coding agents did. I described features, the agent shipped working code, and that code carried a handful of patterns that quietly defeat scale-to-zero. That's not a confession of bad engineering. It's just what building looks like in 2026. Most of us are vibe-coding onto serverless and cloud infra now, and the agent optimizes for "make the feature work," not "keep the database asleep when no one's around." It has no idea your compute bills by the hour it stays awake, so it has no reason to care. That's the whole
AI 资讯
Presentation: Practical Performance Tuning for Serverless Java on AWS
AWS Hero Vadym Kazulkin explains how to overcome Java’s enterprise hurdle on AWS Lambda: cold starts and memory footprints. He shares a technical deep dive into performance tuning, comparing fully managed AWS SnapStart (with pre-snapshot priming hooks) against GraalVM ahead-of-time compilation, while addressing the latest architectural implications of Project Leyden and Java 25. By Vadym Kazulkin
AI 资讯
Kiro as AI Partner for MS SQL Server Optimization on .NET Core: Yang Biasa Berhari-hari, Sekarang Hitungan Jam
Dulu, nyari query yang bikin database spike itu bisa makan berhari-hari. Yang nyari capek, yang nge-fix juga capek. Sekarang? Hitungan jam — dan bonusnya, sambil belajar hal baru juga. Ceritanya begini. Kalau kamu pernah kerja di aplikasi yang pakai ORM (Object-Relational Mapping — semacam "penerjemah otomatis" antara code dan database), pasti familiar sama situasi ini: database tiba-tiba lambat, kamu dapet raw query yang jadi biang kerok, tapi di codebase kamu nulis pakai syntax ORM yang bentuknya beda jauh dari SQL mentah itu. Buat yang belum pernah deal sama ORM, bayangin gini: kamu nulis pesan dalam bahasa Indonesia, lalu ada "penerjemah otomatis" yang convert jadi bahasa Jepang sebelum dikirim ke penerima. Suatu hari ada masalah di pesan yang terkirim — tapi kamu cuma bisa lihat versi bahasa Jepang-nya. Nyari bagian mana dari tulisan Indonesia kamu yang bikin terjemahan-nya bermasalah? Itu effort-nya yang bikin pengen balik tidur aja. Sekarang dengan bantuan Kiro, cukup kasih raw query + akses ke codebase, dia otomatis nyari bagian mana di code yang nge-generate query bermasalah itu. Yang dulu butuh berhari-hari, sekarang bisa selesai dalam hitungan jam — dan itu baru tahap investigasi, belum termasuk fixing-nya. Ceritanya Kenapa Bisa Pakai Kiro Akhir-akhir ini lagi aktif pakai Kiro di tempat kerja. Awal tahun lalu kantor dapat credits melalui program Kiro for Startup , jadi ya sekalian dimaksimalkan. Selain buat debug dan explore query di MS SQL Server, kadang pakai Kiro juga buat analisa log AWS CloudWatch — sambil kasih context aplikasi yang running biar analisa-nya lebih akurat dan gak generic. Di tulisan kali ini, saya mau sharing gimana pakai Kiro sebagai partner beberapa minggu terakhir buat improve query performance di aplikasi .NET Core. Kenapa "partner"? Karena Kiro-nya gak boleh langsung akses ke database — jadi wajib melalui perantara saya. Kita discuss, kolaborasi, dan nge-solve bareng. Bukan AI yang dikasih tombol terus disuruh jalan sendiri. Wakt
AI 资讯
⚠️ The Kotlin Multiplatform division-by-zero trap
If you write Kotlin Multiplatform code that involves integer division, you may have already hit this: the exact same expression behaves completely differently depending on which platform compiles it. 🐛 The problem Take this innocuous expression: val quotient = 12 / 0 val remainder = 12 % 0 On JVM and Native , both lines throw an ArithmeticException . That is the behavior most Kotlin developers expect and design around. On JavaScript , both lines execute without any exception and silently return 0 . Here is a concrete illustration drawn directly from the Kotlin test suites for each platform: // Kotlin/JS check ( 12 / 0 == 0 ) // passes — no exception check ( 12 % 0 == 0 ) // passes — no exception // Kotlin/JVM and Kotlin/Native val quotient : Result < Int > = runCatching { 12 / 0 } val remainder : Result < Int > = runCatching { 12 % 0 } check ( quotient . exceptionOrNull () is ArithmeticException ) // passes check ( remainder . exceptionOrNull () is ArithmeticException ) // passes Summary table: Expression JVM / Native JavaScript 12 / 0 ArithmeticException 0 12 % 0 ArithmeticException 0 🤔 Why it happens On Kotlin/JS, Int values are represented as JavaScript numbers, and 12 / 0 evaluates to Infinity while 12 % 0 evaluates to NaN . Kotlin/JS truncates Int arithmetic to 32 bits using JavaScript's | 0 operator, and per the ECMAScript ToInt32 conversion, both Infinity | 0 and NaN | 0 evaluate to 0 — so the division-by-zero result silently becomes 0 , with no exception thrown. JVM and Native follow Java's long-standing contract: integer division by zero is always an ArithmeticException . The practical consequence is that any guard you write and test on JVM — a try/catch(ArithmeticException) or a pre-condition check that relies on an exception — is silently bypassed when the same code runs on JS. No compile error, no warning, just a wrong result. ✅ The fix: Integer from Kotools Types 5.1.1 The Integer type in Kotools Types explicitly checks for a zero divisor before delegat
AI 资讯
Meet Lunarr: a self-hosted media server for local and SFTP libraries
I have been building Lunarr , a self-hosted web media server for people who want to scan, organize, and watch their own movie and TV libraries in the browser. It is still early, but the core idea is simple: Add local or SFTP media libraries, scan them, match metadata, and play them through a clean web UI. Lunarr is not trying to replace Plex or Jellyfin overnight. Those projects are mature and cover a huge surface area. Lunarr is currently focused on being small, direct, and practical for self-hosted setups where media may live on the same machine or on remote SFTP storage. What Lunarr does today Lunarr currently supports: Local movie and TV libraries SFTP movie and TV libraries TMDb metadata matching Movie, show, season, and episode organization Browser playback Direct streaming when the browser can play the file Temporary HLS remux/transcode when needed Seekable request-driven HLS playback Sidecar .vtt subtitle detection Admin/user accounts Library sharing controls Manual scans, scheduled scans, and local file watching Docker deployment The SFTP support is one of the important parts for me. A lot of self-hosted setups do not keep media on the same machine as the web app. Lunarr can scan remote folders and, when possible, play seekable remote media without first copying the whole file locally. Playback model Lunarr tries direct playback first when the browser can handle the file. When direct playback is not suitable, Lunarr uses temporary HLS playback. Instead of transcoding an entire movie up front, it generates segments around what the player is actually requesting. For example, if you jump from 55 minutes to 13 minutes and then to 80 minutes, Lunarr does not transcode everything between those points. It repositions FFmpeg, generates the requested segment, and prepares a small lookahead window so playback can continue. That keeps CPU and disk usage more proportional to what the viewer is actually watching. Quick start with Docker docker run -d \ --name lunarr \ -
AI 资讯
1- AWS Serverless: Designing a serverless API: Order Processing API (E-commerce)
Modern enterprise order processing architectures must decouple synchronous client demands from asynchronous backend dependencies. Here I'll detail a highly scalable, fault-tolerant design built on AWS. By utilizing an automated API Gateway entry point, specialized Amazon Cognito authentication, optimized AWS Lambda logic blocks, an engineered RDS Proxy connection layer, and an event-driven SQS/EventBridge core, the design guarantees isolation, cost efficiency, and sub-millisecond structural routing. The Scenario User places an order → payment is processed → inventory updated → confirmation email sent Client → API Gateway (Cognito auth + validation) → Order Lambda (business logic + DynamoDB write) → SQS (payment queue) → Payment Lambda → EventBridge → Inventory Lambda → Notification Lambda (SES) 1- Entry Point — API Gateway REST endpoint: POST /orders Request validation via API Gateway models (reject malformed payloads instantly, no Lambda invoked) Auth via Cognito User Pool Authorizer — validates JWT token on every request How It Works The Request Hits: A client sends a POST /orders request with a JWT token in the header. Auth Check: API Gateway automatically intercepts the request and validates the JWT against the Cognito User Pool. If expired or spoofed, it returns 410 Gone / 401 Unauthorized right there. Payload Check: Next, it compares the body against your JSON Schema Model. If a required field like customer_id is missing, API Gateway instantly drops it with a 400 Bad Request. The Win: Your downstream services (like Lambda) are never invoked for bad/unauthorized requests, saving compute costs and protecting against basic DDoS or bad actor spam. Gotchas Cognito Latency: While Cognito authorizers are native, they can add a slight latency overhead to your API's P99 metrics during peak traffic. For massive global scale, some enterprises migrate to custom Lambda Authorizers that cache tokens in ElastiCache (Redis). Model Validation Limits: API Gateway's built-in val
开发者
IP geolocation with zero external APIs, the Cloudflare Workers cf object
When I built whatsmy.fyi , I assumed I'd need a geolocation provider: MaxMind, ipinfo, ip-api, pick your poison. They all mean the same thing: an external dependency, an API key, a quota, added latency, and someone else's server seeing your users' IPs. Then I found out Cloudflare Workers makes the whole category unnecessary. The cf object Every request that hits a Cloudflare Worker carries a request.cf object, populated at the edge before your code even runs. No lookup, no latency, no key. Here's what's inside: { asn : 34984 , // ISP's autonomous system number asOrganization : " Superonline " , // ISP name city : " Istanbul " , region : " Istanbul " , country : " TR " , continent : " AS " , isEUCountry : undefined , // "1" if EU, undefined otherwise latitude : " 41.01380 " , // string, not number! longitude : " 28.94970 " , postalCode : " 34000 " , timezone : " Europe/Istanbul " , colo : " IST " , // which CF datacenter handled this clientTcpRtt : 12 , // user's RTT to the edge, in ms httpProtocol : " HTTP/3 " , tlsVersion : " TLSv1.3 " , tlsCipher : " AEAD-AES128-GCM-SHA256 " } That last group surprised me most: you get the user's HTTP protocol, TLS version, and actual TCP round-trip time for free. Try getting that from a geo API. A complete IP endpoint in ~30 lines export default { async fetch ( request ) { const cf = request . cf ?? {}; const ip = request . headers . get ( " CF-Connecting-IP " ); return Response . json ({ ip , city : cf . city ?? null , country : cf . country ?? null , isp : cf . asOrganization ?? null , asn : cf . asn ?? null , timezone : cf . timezone ?? null , lat : cf . latitude ? parseFloat ( cf . latitude ) : null , lng : cf . longitude ? parseFloat ( cf . longitude ) : null , protocol : cf . httpProtocol ?? null , tls : cf . tlsVersion ?? null , rttMs : cf . clientTcpRtt ?? null , }); }, }; That's the entire backend. No database, no GeoIP file to update monthly, no vendor. The gotchas (learned the hard way) 1. Coordinates are strings. lati