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
AI 资讯
Upstash Redis + Next.js: The Complete Guide (2026)
Redis is fast. But self-hosting Redis on a serverless stack is a nightmare — cold starts, connection pool exhaustion, and managing a persistent server that your serverless functions keep hammering. Upstash solves this with an HTTP-based Redis API that scales to zero, charges per request, and works natively with Next.js App Router. This guide covers the patterns that actually matter in production: cache-aside with proper TTLs, SWR (stale-while-revalidate), session storage, and pub/sub. Real code, real trade-offs. Read the full article with all code examples at stacknotice.com Why Upstash Over a Traditional Redis Instance Standard Redis uses persistent TCP connections. Serverless functions don't maintain persistent connections — every invocation potentially opens a new one. At scale, you hit ECONNREFUSED or max connection errors that are annoying to debug and expensive to fix. Upstash's @upstash/redis client talks over HTTP/REST. No connection pool, no connection limit headaches. Each request is stateless. This is exactly what Next.js Server Components and Route Handlers need. Other advantages: Pay per request — a cache that never gets hit costs $0 Global replication — low latency from any Vercel edge region Native Edge Runtime support — works in Next.js middleware Free tier — 10,000 commands/day, no credit card needed Setup npm install @upstash/redis // lib/redis.ts import { Redis } from ' @upstash/redis ' export const redis = new Redis ({ url : process . env . UPSTASH_REDIS_REST_URL ! , token : process . env . UPSTASH_REDIS_REST_TOKEN ! , }) Pattern 1: Cache-Aside // lib/cache.ts import { redis } from ' ./redis ' export async function withCache < T > ( key : string , fetcher : () => Promise < T > , options : { ttl ?: number ; prefix ?: string } = {} ): Promise < T > { const { ttl = 300 , prefix = ' cache ' } = options const cacheKey = ` ${ prefix } : ${ key } ` const cached = await redis . get < T > ( cacheKey ) if ( cached !== null ) return cached const data = awai
AI 资讯
Why Your Vector Database Is Overpriced: Lucene's 32x Compression and Serverless Economics
Why Your Vector Database Is Overpriced: Lucene's 32x Compression and Serverless Economics In 2026, the boundary between "search engine" and "AI infrastructure" has dissolved. What started as text indexing has become the backbone of retrieval-augmented generation, vector databases, and serverless AI pipelines. This is the story of how the oldest search technology in the Java ecosystem became the most important infrastructure you've never noticed. The Convergence No One Saw Coming Five years ago, if you said Apache Lucene would power the next generation of AI infrastructure, you'd have been laughed out of the room. Lucene was the boring Java library that powered Elasticsearch — reliable, yes, but hardly exciting. The action was in vector databases: Pinecone, Weaviate, Qdrant. The cool kids had moved on. That narrative died in 2025. What happened was a structural inversion. While vector-native databases optimized for one thing (fast similarity search), the real production pain points were everywhere else: hybrid search, metadata filtering, provenance tracking, multi-tenant security, and — most critically — the ability to query both your documents and your vectors in a single, unified system. Lucene didn't just survive this transition. It engineered it. Through a series of aggressive, hardware-native optimizations between versions 10.0 and 10.4, Lucene transformed from a text indexer into a vector search kernel capable of outperforming specialized databases while maintaining the operational maturity that enterprises actually need. And Elasticsearch, riding on Lucene's coattails, didn't just integrate vectors — it re-architected itself into a stateless, serverless platform that happens to do search. This post examines three layers of that transformation: the engine (Lucene), the platform (Elasticsearch), and the architecture (AI-native search infrastructure). Each layer tells a different story, but they share a common thread: the future of AI infrastructure is being buil
AI 资讯
I Tested 9 Serverless GPU Providers for AI Inference in 2026. Here's What I'd Actually Use
TL;DR If you're shipping AI inference and tired of babysitting GPUs, serverless is the way out. You deploy the model, the platform scales it from zero to hundreds of GPUs and back, and you only pay for the time you actually use. If I'm picking one to start with, it's DigitalOcean . It's got the widest GPU lineup of any serverless provider (RTX 4000 Ada all the way up to NVIDIA Blackwell B300 and AMD's MI350X), one API and one bill instead of five, and it's simple enough to ship on without a sales call. (More on why that one's personal for me below.) Below I compare 9 providers across the things that actually matter: GPU specs, per-hour pricing, cold-start latency, model support, and how nice they are to build on. DigitalOcean, RunPod, Modal, Koyeb, Together AI, Replicate, Baseten, Fal, and Cloudflare Workers AI each win at something different, from cheap experimentation to global edge inference. Contents Why I ran this The field at a glance How I evaluated these providers Per-provider analysis: DigitalOcean RunPod Modal Koyeb Together AI Replicate Baseten Fal Cloudflare Workers AI Why I keep coming back to DigitalOcean The short version Questions I actually get asked Why I ran this Quick note on why this exists. At work I get a front-row seat to a lot of people shipping an AI model into production for the first time: students, first-time founders, my own team. And lately the same question keeps coming up: where do I actually run this thing? I was tired of answering with a shrug and "it depends," so I did the homework myself. Signed up, read the pricing pages, ran the comparisons, and wrote it all down. Nobody's a real expert at this yet, me included, so I'd rather share my notes and get corrected than pretend I've got it figured out. And here's the thing about AI inference in 2026: demand blew past what the old way of provisioning GPUs can handle. Teams that used to wait weeks for dedicated hardware now need a model live in minutes. The ground moved. And the stuff t
AI 资讯
What I Learned Building a Product Review Platform Using ASP.NET Core and SQL Server
When I started building OpinioZone , my goal was simple: create a platform where users could compare products, read reviews, and make informed buying decisions. At first, it seemed like a straightforward web application. Store products, display specifications, and allow users to browse information. However, as the platform grew, I quickly discovered that building a review and comparison website involves many technical and architectural challenges. Choosing the Technology Stack I selected ASP.NET Core as the primary framework because of its performance, flexibility, and long-term support. For data storage, I chose SQL Server since it provides strong reliability and works well with complex relationships between products, categories, reviews, ratings, and specifications. This combination allowed me to build a scalable foundation while keeping development manageable. Designing the Database One of the biggest challenges was designing a database structure that could support multiple product categories. A smartphone and a car have very different specifications, but the platform needed to handle both efficiently. Instead of creating completely separate systems, I designed a flexible structure that could store category-specific attributes while maintaining a consistent user experience. This decision made it easier to add new product categories without major database changes. Building Product Comparisons The comparison feature became one of the most important parts of the platform. Users expect side-by-side comparisons to load quickly and display meaningful differences between products. To achieve this, I had to optimize queries and carefully structure specification data. Performance became increasingly important as the number of products grew. SEO Challenges For a content-driven website, SEO is critical. Every product page requires: Unique titles Descriptions Structured content Internal linking Fast page loading One lesson I learned early was that technical SEO and content q
AI 资讯
Serverless Framework Deployment: Unleash the Power of AWS Lambda
Let me tell you exactly what happened the first time I tried to set up Lambda manually. Four hours. IAM trust policies I didn't fully understand, ARNs copy-pasted into the wrong fields, an API Gateway that was technically configured but somehow not routing anything correctly, and a deploy that failed with an error message pointing me nowhere useful. I hadn't written a single line of actual business logic yet. That's when someone on my team mentioned the Serverless Framework. My first reaction was honestly skepticism — another abstraction layer sounded like another thing to learn and eventually fight with. I was wrong about that. This isn't a "look how clean this tool is" post. It's more like: here's what I actually did to get a Postgres-backed CRUD API running on Lambda, step by step, including the parts that tripped me up. What the Framework Is Actually Doing Under the Hood Worth knowing before you start: the Serverless Framework isn't magic. It's generating CloudFormation templates and submitting them to AWS on your behalf. Your Lambda functions, API Gateway routes, CloudWatch log groups — all of it gets provisioned from a single config file. It works with other providers too, but the AWS integration is where it really earns its keep. The console clicking and manual ARN-wiring that burns time at the start of every serverless project? Gone. Same deploy workflow whether you're building a REST API, an event processor, or a cron job. Once you've done it once, the second project takes a fraction of the time. What You're Building Four live endpoints backed by PostgreSQL. A Users table. Create, read, update, delete — nothing exotic, but a real enough foundation that you can extend it into something actual once this guide is done. You'll need an AWS account, the AWS CLI installed, and the Serverless Framework installed before starting. That's it. Step 1: Sort Out Your AWS Credentials Run this to create both config files in one go: bash cat << EOF > ~/.aws/credentials [def
AI 资讯
Vercel cron alternative: what to use when built-in cron isn't enough
Vercel's built-in cron triggers your serverless functions on a schedule. For simple use cases it works. But it has no failure alerts, no execution history on the Hobby plan, and no way to know whether your function actually completed successfully — only that it was called. Where Vercel cron falls short Vercel cron works by invoking one of your API routes on a schedule defined in vercel.json . The invocation is fire-and-forget — if your function times out, throws an error, or returns a non-2xx status, you get no alert. You find out when a user reports something is broken. The specific gaps developers run into: No failure alerts. Vercel does not send an email or webhook if your scheduled function fails. No execution history on Hobby. The free plan does not retain cron execution history. Timeout ceiling. Functions are subject to the same timeout limits as all serverless functions — 10 seconds on Hobby, up to 300 seconds on Pro. HTTP-only. Vercel cron calls an HTTP endpoint on your app. You cannot schedule arbitrary background work outside your deployment. No heartbeat monitoring. Even if your function is called successfully, you have no built-in way to verify it completed its work — only that it was invoked. Minimum 1-hour interval on Hobby. Sub-hourly schedules require a paid plan. If you are hitting any of these limitations, you need an external tool. Comparison at a glance Tool Schedules jobs Failure alerts Heartbeat Uptime monitoring Free tier Vercel built-in ✓ ✗ ✗ ✗ ✓ (1h min) Tickstem ✓ ✓ ✓ ✓ ✓ Upstash QStash ✓ ✓ (retries) ✗ ✗ ✓ Inngest ✓ ✓ ✗ ✗ ✓ cron-job.org ✓ ✓ (basic) ✗ ✗ ✓ Tickstem — cron + heartbeat + uptime in one API key Best for: developers who need scheduling, failure alerts, heartbeat monitoring, and uptime checks without managing multiple tools. Tickstem is an external HTTP cron scheduler with built-in monitoring. You register your Vercel endpoint as a cron job, and Tickstem calls it on your schedule — every minute if needed, regardless of your Vercel
AI 资讯
From pg-boss to Cloud Tasks: Fixing Queue Bursts and DB Connection Failures on Serverless
At Twio we picked pg-boss for our job queue, ran into trouble when we went serverless, looked at Pub/Sub, and ended up on Google Cloud Tasks. This is what each queue got right, what it got wrong for our workload, and the rule we landed on for choosing between them. The workload Twio is an AI SaaS for loan brokers. The piece that needs a job queue is email processing: download an email, parse the body and attachments, OCR, classify with an LLM, write structured data, and index for RAG. One email with five attachments easily becomes 30+ background jobs. A batch upload becomes hundreds. Why pg-boss worked — until it didn't Our database was Postgres on Neon, so pg-boss was the obvious starting point. No extra infrastructure, and one feature we genuinely loved: transactional enqueue . Because jobs live in the same database as business data, you can create a job in the same transaction as the row that triggered it. No dual-write problem, no "DB succeeded but the queue API failed" inconsistency. It also gave us retries, delayed jobs, dead-letter queues, dedup keys, and full SQL visibility into stuck or failed jobs. For a Postgres-first app on always-on infra, it's an excellent tool. Then we moved heavy processing to Cloud Run, and the cracks showed up. pg-boss polls. Neon suspends. They want opposite things. pg-boss runs a query roughly every 1–2 seconds to look for the next job, plus maintenance queries. Neon autosuspends compute when nothing touches the database. If the queue is polling every second, Neon's idle timer never expires — you pay for always-on compute even when the queue is empty. Worse, when Neon did manage to suspend, the next poll had to wake it. That wake-up takes hundreds of ms to a few seconds, and queries that triggered it would fail with Connection terminated , ECONNRESET , or timeouts. Pooled connections made it worse: the pool kept sockets that the server had already closed during suspend, and the next polling cycle picked one up and broke. This isn
AI 资讯
S3 zipper challenge: a parallel zip assembly that beats the single Lambda approach
I recently read Jérémie Rodon's excellent article On-Demand Archives on S3 , where he describes an elegant Rust solution for zipping 3,000 × 5MB files from S3 within a single Lambda function. His approach is impressive: streaming a ZIP archive through a custom Rotating Slab Buffer, saturating bandwidth with concurrent downloads, all within 512MB of RAM. The result: 3 minutes 35 seconds . I thought it was a good challenge to reach better performance. His article ends with an open invitation: "do you think you can do better with your favorite language?" Well, my favorite language is not Rust nor Go nor.. however, I'm fluent in serverless ;) so I took a different angle entirely. A Different Approach: Why Not Parallelize the Problem? Jérémie's constraint was a single Lambda. That's elegant, but it means you're bound by one machine's network bandwidth (~600 Mbps). No matter how perfect your streaming is, physics wins: 15GB at 600 Mbps ≈ 200 seconds minimum. My question was: what if we break that single-machine bottleneck? The key insight is that ZIP files in STORE mode (no compression) have deterministic byte offsets . Each entry is exactly 50 + len(filename) + filesize bytes (local header + ZIP64 extra field + data). If you know all filenames and sizes upfront, you can pre-calculate exactly where every file will land in the final archive, before downloading a single byte. This means independent workers can each build their portion of the zip in parallel, and S3's multipart upload lets them write their chunks independently (parts can be uploaded in any order by different processes sharing the same upload ID). Architecture Planner Lambda → Step Functions Distributed Map → N Worker Lambdas → Finalizer Lambda │ │ │ │ │ │ CreateMultipartUpload │ │ │ UploadPart (parallel) │ CompleteMultipartUpload ▼ ▼ ▼ ▼ ▼ S3 Output Bucket Planner : Lists all source files, computes zip byte offsets, initiates multipart upload, divides work into balanced batches (equal data volume per worker)
AI 资讯
Developer will need to understand lambda by 2026
I used to deploy Node.js apps on EC2 and manage servers like it was my second job. Port configs. PM2 restarts. Nginx rewrites. SSL renewals. Then I ran my first AWS Lambda function. 80% of that work is gone. Here's what Lambda actually does that nobody explains clearly: → You write a function → AWS runs it ONLY when triggered → You pay for milliseconds of execution → It scales from 1 to 1,000,000 requests without you touching anything As a full-stack developer in Bahrain, preparing for my AWS Developer Associate exam, this is the shift that changes how you think about backend architecture. Not "how do I manage a server" but "what should happen when this event fires." That mental model switch took me a week to fully get. I'm documenting everything as I study. Drop a 🔥 if you want me to share my Lambda notes weekly.
AI 资讯
I Built pretext-pdf: Serverless PDFs Without Chromium
I Built pretext-pdf: Serverless PDFs Without Chromium I got frustrated with PDF generation in Node.js. Every tool had trade-offs, and none of them felt right. The Problem Every time I needed to generate PDFs programmatically, I hit the same walls: Puppeteer — Renders HTML to PDF beautifully, but takes 500ms-2s per page. Way too slow for batch operations. wkhtmltopdf — Old, fragile, breaks in production, dependency hell. pdfmake — Good for simple invoices, falls apart with complex layouts. All of them — Overkill if you're not rendering HTML. And here's the kicker: I didn't need to render HTML. I had structured data (invoices, reports, certificates) that I needed to turn into PDFs programmatically . The Solution I built pretext-pdf — a JSON-based PDF generation library. Instead of: javascript // ❌ Puppeteer: render HTML const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.setContent(html); const pdf = await page.pdf(); // 1000ms+ You do: // ✅ pretext-pdf: define structure const doc = { sections: [ { type: 'heading', text: 'Invoice' }, { type: 'table', rows: [...] } ] }; const pdf = await renderPDF(doc); // 40-100ms No Chromium. No external dependencies. Pure Node.js. Why This Matters If you're building: ✅ Invoice generation systems ✅ Dynamic reports for your SaaS ✅ AI agents that create PDFs (Claude, Cursor, Windsurf) ✅ Certificate systems ✅ Multi-language documents ...pretext-pdf is built for you. Today: v2.0.14 Launch I just shipped a major upgrade. The text layout engine (which handles how words break across lines) is now significantly better: Better CJK + Latin mixed-script handling Smarter punctuation (quotes stay with their text) 7-12% faster Zero breaking changes The Stats 337 tests passing — production-ready 0 critical vulnerabilities — secure MIT licensed — free to use Open source — contribute or fork Technical Foundation The layout engine is based on pretext by Cheng Lou (React core team). I cherry-picked 11 patches for