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

标签:#dev

找到 4339 篇相关文章

AI 资讯

Astro Introduces Sätteri: A Rust-powered Markdown And Mdx Processor With Up To 60% Faster Builds

Sätteri is a high-performance Markdown and MDX processor developed by the Astro team. Built in Rust, it enhances build speeds by up to 61% for Astro 7.0. Sätteri supports flexible JavaScript plugins and integrates various Markdown features natively. It maintains compatibility with the unified ecosystem while offering faster parsing and reduced dependencies. By Daniel Curtis

2026-08-27 原文 →
AI 资讯

Everyone is getting ready for WCAG 2.2. Two thirds of Europe's biggest sites still fail 2.1 Level A.

The next version of the European accessibility standard is scheduled for citation on 30 November 2026. EN 301 549 V4.1.1 swaps WCAG 2.1 for WCAG 2.2, and six new success criteria arrive at levels A and AA. There is a small industry of readiness checklists for it already. So I measured what the current version looks like first. The answer is that the deadline people are preparing for is not the one they have missed. I scanned the most-visited websites on EU country domains and counted which clauses of EN 301 549 they fail today, under the version cited right now. Not the one arriving. The one in force since before the European Accessibility Act deadline passed in June 2025. Sixty-four per cent fail clause 9.4.1.2, Name, Role, Value. It is Level A, the lowest bar the standard has, and it has been in every version of WCAG since 2008. Here is the full picture, and then the reasons to distrust parts of it. What was measured Clause Criterion Level Sites failing 9.4.1.2 Name, Role, Value A 96 of 149 (64%) 9.1.4.3 Contrast (Minimum) AA 66 of 149 (44%) 9.2.4.4 Link Purpose (In Context) A 53 of 149 (36%) 9.2.5.8 Target Size (Minimum) AA 51 of 149 (34%) 9.1.1.1 Non-text Content A 35 of 149 (23%) 9.1.3.1 Info and Relationships A 27 of 149 (18%) Target size is the odd one out: it is a WCAG 2.2 criterion and not currently required. It is in the table because it is the only one of the six arriving in V4.1.1 that the rule engine used here has a check for, which is a point I will come back to. Thirty-two sites of the 149, about one in five, failed nothing that automated testing can detect. That is not the same as passing. Two of those rows are not independent. The rule that most often breaks Name, Role, Value is a link with no accessible name, and the same defect also fails Link Purpose. One missing label lands in two rows of that table. I am pointing this out because a table of six numbers implies six problems, and some of them are the same problem counted twice under different cla

2026-08-27 原文 →
AI 资讯

validateHttp() Has No Async Machinery: A Trace From Signal Forms Down to fetch() 🔍🚀

Let's be honest: async validation is the part of any forms library where you brace yourself. Debouncing, cancelling the request the user just invalidated by typing another character, keeping a "checking..." spinner honest, not letting a slow response overwrite a fast one. Every library that has ever done this has grown a pile of bespoke machinery for it. So when Signal Forms shipped validateHttp() and it just worked, I wanted to see the pile. I opened the source expecting a few hundred lines of async bookkeeping, and instead found a function whose entire body is a single call to something else. That turned into a trace all the way down, from a form field to the line where bytes actually leave the browser. Six layers, and only two of them add anything you could call new async machinery. ✅ Availability: validateHttp() is @publicApi 22.0 , stable. Every source reference in this article is pinned to the v22.1.1 tag , so the line numbers stay valid even as main moves. 🧩 The View From Outside The usage is unremarkable, which is the point. You declare that a field validates against an endpoint, and you're done: const schema = form ( this . model , ( path ) => { validateHttp ( path . username , { request : ({ value }) => `/api/username-available?u= ${ value ()} ` , debounce : 300 , onError : () => ({ kind : ' server-unreachable ' }), onSuccess : ( res : { available : boolean }) => res . available ? undefined : { kind : ' username-taken ' }, }); }); Sync validators run first, the request waits until they pass, field().pending() is true while it's in flight, and typing again cancels the previous call. If you've read Part 3 of my Signal Forms series , that's the behaviour contract you already know. The question here is who implements it. 🔍 Layer 1: validateHttp() Is a Delegation Here is the whole function, from validate_http.ts : export function validateHttp ( path , opts ) { validateAsync ( path , { params : opts . request , debounce : opts . debounce , factory : ( request )

2026-08-27 原文 →
AI 资讯

wkhtmltopdf in Docker in 2026: musl, libssl1.1, and the ways out

Disclosure up front: I'm Vitalii, founder of PDFik , a hosted URL/HTML-to-PDF API. It shows up once near the end, clearly marked. The rest of this is the debugging guide I wish existed the last three times someone hit these errors. If you run wkhtmltopdf in containers, you have probably met at least one of these three errors: sh: /usr/local/bin/wkhtmltopdf: not found # Alpine wkhtmltox : Depends: libssl1.1 but it is not installable E: Unable to locate package wkhtmltopdf # Ubuntu 24.04 / Debian 13 All three have the same root cause: the project is archived (January 2023, repository read-only ) and the last official packages were built in May 2023 — release 0.12.6.1-3 , whose newest targets are Debian 12 (bookworm) and Ubuntu 22.04 (jammy). The distros kept moving; the binaries stopped. Here is what each error actually means, the recipe that still works in 2026, and the honest exits. Error 1: not found on Alpine — it's not about PATH The confusing part: the file is there, ls sees it, and the shell still says not found . That message comes from the kernel failing to load the binary's interpreter: official wkhtmltopdf builds link against glibc , Alpine ships musl , and the referenced dynamic loader ( /lib64/ld-linux-x86-64.so.2 ) does not exist on Alpine. ldd /usr/local/bin/wkhtmltopdf shows it immediately. There is no supported way around it on Alpine today: the distro dropped its wkhtmltopdf package years ago (nothing in current stable), and gcompat shims are a lottery with a binary this large. If the container must run wkhtmltopdf, don't build it on Alpine — that fight is not worth the ~50 MB you save. Error 2: Depends: libssl1.1 — you're installing a 2020 build on a 2023+ distro The widely-copied Dockerfiles fetch wkhtmltox_0.12.6-1.*.deb , which links OpenSSL 1.1. Debian 12, Ubuntu 22.04+ and everything after ship OpenSSL 3 and removed libssl1.1 from the archives, so the dependency is unresolvable. (Pinning an EOL base image or hand-installing an EOL libssl to wor

2026-08-27 原文 →
AI 资讯

Presentation: Python, Numba, and Algorithm Design: Building Efficient Models in Financial Services

Chad Schuster discusses bridging Python's developer velocity with C-like performance using Numba JIT and GPUs. Drawing from large-scale actuarial modeling, he explains LLVM pipeline architecture, performance gains up to 750x, and essential trade-offs like OOP limits, type inference errors, and compile-time overhead for engineering leaders scaling compute-heavy enterprise systems. By Chad Schuster

2026-08-27 原文 →
AI 资讯

I Ran 89,479 WhatsApp Messages Through WAHA. Twilio: $604.

Last month my WhatsApp stack moved 89,479 messages. I got no invoice for any of them. That is not a brag, it is the setup for an honest accounting. Because "self-hosting is cheaper" is the least interesting sentence in infrastructure, and it is usually said by someone who has never been paged at 7am by a bot that went quiet at 2am. I want to put a real number on both sides of that trade: the money Twilio would have charged, and the money self-hosting quietly takes back. All the numbers below were pulled or fetched on August 27, 2026 . The rate cards move quarterly, so check yours. The traffic, measured rather than estimated Five WhatsApp inboxes, bridged from WAHA into a self-hosted Chatwoot. Thirty days: messages Total 89,479 Inbound (from users) 45,563 Outbound (from us) 43,916 Most benchmarks stop here, multiply by a per-message rate, and publish. That answer is wrong, because Meta does not charge per message. It charges per template sent outside an open customer service window. Multiplying my full 89,479 by a template rate overstates the Meta line by about 3x. Multiplying just the outbound half still overstates it by about 1.5x. Since November 1, 2024 non-template messages are free. Since July 1, 2025 utility templates answering a user inside an open 24-hour window are also free. So the only line that costs money is the outbound message that goes out when nobody has written to you in the last day. Which means the number you actually need is not "how many messages," it is "how many outbound messages had no inbound message from that contact in the preceding 24 hours." The query that produces the real bill Here it is against Chatwoot's schema. It uses a window function rather than a correlated NOT EXISTS , because on a messages table of any size the correlated version will happily eat your connection pool. WITH src AS ( SELECT m . conversation_id , m . created_at , m . message_type FROM messages m WHERE m . inbox_id IN ( 27 , 23 , 46 , 50 , 48 ) -- your WhatsApp in

2026-08-27 原文 →
AI 资讯

Are websites still relevant today for the average person?

The average person does not wake up choosing between "website" and "no website." They choose between opening an app, asking ChatGPT, tapping a map result, or typing a URL. Websites are still relevant when those paths need a place to land: confirm a business is real, compare two options side by side, pay for something, book a slot, or read instructions that outlive a chat thread. They become irrelevant when the destination is slow, broken, or empty, because the next tap is always available. That shift is what agencies miss when the brief says "we need a website" as if presence alone still wins. In 2026 a site is less often where people first find you and more often where they check you are real, pay, or book after they found you somewhere else. Your job is not only to exist on the open web. It is to be the destination that still earns the click when someone is ready to act. What does "still relevant" mean after apps and AI answers? Relevance is not traffic volume. Pew Research analysis of tens of thousands of Google searches in 2025 found users clicked a traditional result on only about 8% of queries that showed an AI Overview, versus about 15% without one. Casual browsing traffic is thinner. The visits that remain often carry sharper intent: someone already heard a name and wants proof, or they are ready to buy and need a form that works on mobile. Google's Search team has argued the same restraint in public: websites are not obsolete, but they are not mandatory for every goal ( Search Off the Record ). Whether you need one depends on audience, control, and what you are trying to deliver. For many businesses the answer is still yes, because apps and social profiles do not replace a site you control when AI systems and search features need structured facts to cite. The relevance question therefore splits in two. Is the open web still where machines and sceptical humans go to verify claims? Yes, for most categories. Is every marketing site still the main place people

2026-08-27 原文 →
AI 资讯

Day 1 of #100DaysOfCode: Built My First Project

Published: 27/08/2026 The Setup I'm 16 years old and starting my coding journey in 2026. After using Twitter, GitHub, and setting up my domain ms.blurbisht.fun, I decided to commit to #100DaysOfCode. The Project: Pong Game CLI A terminal-based two-player Pong game built with Python's curses library. Demonstrates: Object-oriented programming Game loops and input handling ASCII graphics animation Score tracking # Key code snippet if key == ord ( ' w ' ): left_paddle . move_up () Why I Built It: To move beyond theory to actual shipping. My goals: learn Python → build AI agents → create multi-agent systems. What's Next: Day 2: Not Planned!! Connect: Twitter: @blurbisht GitHub: github.com/BlurBisht Portfolio: ms.blurbisht.fun

2026-08-27 原文 →
AI 资讯

EC2 + S3 + RDS + Lambda: Now AWS Finally Makes Sense

When I first looked at AWS, it felt unnecessarily complicated. EC2 runs something. S3 stores something. RDS manages something. Lambda does something “serverless.” I understood the definitions individually. But I still didn't understand AWS. The breakthrough comes when you stop learning these services separately and ask one simple question: How would I use EC2, S3, RDS and Lambda together to build one real application? That's when AWS starts making sense. So instead of another article explaining AWS services like dictionary definitions, let's build something. Imagine we're creating a simple job portal where users can create accounts, upload resumes and apply for jobs. Nothing extraordinary. But this small application is enough to understand some of the most important ideas in cloud architecture. First, Forget AWS for a Minute Before choosing any AWS service, think about what our application actually needs. Someone visits our website. They create an account. They upload their resume. They browse available jobs. They submit an application. When a resume is uploaded, perhaps we want to automatically process it and extract some basic information. Already, we can identify four different technical problems. We need somewhere to run our application. We need somewhere to store uploaded files. We need somewhere to store structured information such as users and applications. And we need something that can automatically react when certain events happen. Now AWS becomes easier. Because instead of memorizing services, we're matching problems to solutions. Our architecture starts with four pieces: EC2 → Application S3 → Files RDS → Structured Data Lambda → Event-Driven Processing Let's see what that actually means. EC2: Where Our Application Lives Our job portal needs backend code. Maybe we're building it using Python, Node.js, Java or another backend technology. That code needs somewhere to run. This is where Amazon EC2 enters the picture. Think of EC2 as renting a computer insid

2026-08-27 原文 →
AI 资讯

How I automated my content distribution with a DSH plugin I scaffolded myself

How I automated my content distribution with a DSH plugin I scaffolded myself Posting is easy. Posting everywhere, consistently, is the hard part. I wanted a single command that takes one markdown article and pushes it to Dev.to, GitHub (as a gist), and eventually Bluesky and Mastodon — without my ever touching those web editors again. So I built it as a plugin for DSH (DeepSeek Harness) , using a scaffolding tool that I published myself. Here's the story, the 3 pitfalls that cost me the most time, and how you can get the same thing running in about a minute. Why automate distribution at all? Writing in public is the cheapest compounding asset a developer has. But cross-posting manually has two failure modes: You skip platforms — the "I'll do it later" tab that stays open forever. You lose the content graph — each platform becomes a silo with a slightly different version. A plugin that accepts content + title + [platforms] and returns per-platform status + links removes both. One source, many destinations, audited every time. What I built A DSH content-automation plugin ( dsh-crosspost ) with: Platform adapters : Dev.to (real), GitHub gist (real), Bluesky + Mastodon (stubs, next milestone). BYOK credentials : your tokens live in your DSH profile config — never in code, no platform approval needed from the plugin author. Error classification : every adapter wraps HTTP in try/catch and returns auth / rate-limit / bad-request instead of a raw stack trace, so an agent can decide to retry or skip per platform. Parallel orchestration : one platform failing never blocks the others. The 3 pitfalls that cost me the most time 1. The stale latest dist-tag (the big one) npm install @deepseek-ai/dsh-tools gives you a stale 0.0.1-rc.1 — the real line lives under the next tag. Wasted an evening debugging failures that were purely "wrong version resolved." Lesson: check dist-tags before installing anything in a fast-moving young ecosystem ( npm view pkg dist-tags ). 2. Pure ESM + b

2026-08-27 原文 →
AI 资讯

Your Free AI Tier Is Shared. Build the Gate.

This week, DEV is arguing about who reviews AI output ( discussion ). The community keeps asking the same question. My answer is different. Review the boundary first, not the output. The output is visible. The boundary is not. That is where the risk hides. Agents get the memory debates. The gateway gets none. A free AI tier is a shared service. It has a budget, a concurrency ceiling, and no SLA. Treat it that way. Put a gateway between your app and the model. The gateway owns the budget, the queue, and the breaker. MonkeyCode is an open source project. It offers free model access and a free server option. The free tier gives you a 10M token monthly budget. That number is a constraint, not a feature. Design around it before you build on it. Disclosure: This article was prepared as part of MonkeyCode's product outreach. Think of the free tier as a water pipe. The pipe has a fixed diameter and a monthly meter. Your app is a set of open taps. Without a valve, the meter empties fast and the pipe floods. The gateway is the valve. Direct calls look simpler. They are simpler for one request. They fail at the tenth. The gateway absorbs the variance. Your app never sees a 429. Your app never sees an empty budget. Constraints Three constraints define the design. First, the 10M token budget is monthly. It does not reset daily. It does not roll over. Second, the free server serializes work. Concurrency of one is a safe assumption. Third, there is no SLA. The endpoint can stall, throttle, or return 429 at any moment. These constraints are not bugs. They are the contract. A good architecture reads the contract. Then it shapes the data flow around it. Data flow The flow has six stages. The client sends a prompt to the gateway. The gateway checks the token budget. It enqueues the request. A single worker drains the queue. The worker calls the model endpoint. The response returns to the client. Add two escape paths. When the budget is empty, the gateway returns a fallback answer. Whe

2026-08-27 原文 →
AI 资讯

drainscan vs gitleaks vs trufflehog: Why Web3 Needs Its Own Secret Scanner (2026 Benchmark)

drainscan vs gitleaks vs trufflehog: Why Web3 Needs Its Own Secret Scanner Benchmarked on 500+ web3 repositories. Generic scanners miss 73% of web3-specific key leaks. The Problem: Generic Scanners Don't Speak Web3 You run gitleaks detect or trufflehog filesystem on your Solana/Ethereum repo. Green checkmark. You ship. Three months later: $2.3M drained from a private key committed in docker-compose.yml that neither tool flagged as high-confidence. Why? Generic scanners match patterns (regex/entropy). They don't understand web3 key semantics : Blind Spot gitleaks trufflehog drainscan BIP-39 checksum validation ❌ ❌ ✅ Offline address derivation ❌ ❌ ✅ Live balance checks ❌ ❌ ✅ Phantom JSON export detection ❌ ❌ ✅ Solana base58 seed (64-byte) Partial Partial ✅ Token-2022 extension context ❌ ❌ ✅ Entropy + context dedup Generic Generic Web3-aware SARIF 2.1.0 ✅ ✅ ✅ Benchmark: 500+ Web3 Repos Scanned Methodology : Cloned top 500 repos by stars from solana , ethereum , defi , web3 topics. Ran each scanner with default + aggressive configs. Manual verification of findings. Results Summary Metric gitleaks trufflehog drainscan Free Total findings 1,847 3,291 2,156 High-confidence true positives 312 401 687 Web3-specific true positives 89 112 487 False positive rate (high) 34% 41% 3% False negative rate (web3 keys) 73% 68% 4% Avg scan time (500 repos) 12m 47m 8m Key Finding: The 73% Gap Generic scanners missed 73% of web3-specific key types : Phantom/Solflare JSON exports (64-byte arrays) — gitleaks: 0, trufflehog: 12, drainscan: 234 BIP-39 mnemonics with valid checksum — gitleaks: 45 (many false), trufflehog: 67, drainscan: 156 (all validated) Solana base58 seeds — gitleaks: 23, trufflehog: 31, drainscan: 189 EVM keys in .env / .yaml / .toml context — gitleaks: 189, trufflehog: 223, drainscan: 298 Entropy-detected foreign-chain keys (Cosmos, Sui, Near, ed25519 hex) — gitleaks: 0, trufflehog: 0, drainscan: 87 Why drainscan Wins on Web3 1. BIP-39 Checksum Validation = Near-Zero Fal

2026-08-27 原文 →
AI 资讯

Stop rewriting your API responses in Laravel (Use this Trait instead)

If you are building API-driven applications, nothing clutters up your controllers faster than manually typing out response()->json(...) arrays every single time you need to return data or throw an error. When you have inconsistent response structures, your frontend (and the developers consuming your API) will constantly have to guess whether the data is nested under ['data'] , ['payload'] , or just at the root of the object. The cleanest way I've found to standardize this across an entire application is by creating a dedicated ApiResponse trait. Instead of rewriting your JSON structure in every controller method, create this trait in your app/Traits directory: namespace App\Traits ; use Illuminate\Http\JsonResponse ; trait ApiResponse { protected function success ( mixed $data , ?string $message = null , int $code = 200 ): JsonResponse { return response () -> json ([ 'status' => 'success' , 'message' => $message , 'data' => $data ], $code ); } protected function error ( string $message , int $code = 400 , array | string $errors = []): JsonResponse { // Force errors into an array format for consistent frontend parsing $formattedErrors = is_string ( $errors ) ? [ $errors ] : $errors ; return response () -> json ([ 'status' => 'error' , 'message' => $message , 'errors' => $formattedErrors ], $code ); } } Next, simply use this trait inside your base Controller.php . Now, your actual endpoints become incredibly readable and strictly standardized: namespace App\Http\Controllers ; use App\Models\Task ; use Illuminate\Http\Request ; use Illuminate\Http\JsonResponse ; use Throwable ; class TaskController extends Controller { public function store ( Request $request ): JsonResponse { $validated = $request -> validate ([ 'title' => 'required|string|max:255' , 'description' => 'nullable|string' ]); try { $task = Task :: create ( $validated ); return $this -> success ( $task , 'Task successfully generated' , 201 ); } catch ( Throwable $e ) { // Note: Exposing raw exception messa

2026-08-27 原文 →
AI 资讯

Azure ExpressRoute vs VPN Gateway: the honest comparison

Your datacenter needs to talk to Azure. You can send that traffic through an encrypted tunnel over the public internet, or over a private circuit that never touches it. That single choice — shared road or private rail — decides cost, speed, and reliability. Almost every organization moving to Azure keeps something on-premises, and those two worlds have to connect privately. Azure gives you two hybrid-connectivity options, and they take opposite routes to the same destination: VPN Gateway and ExpressRoute . Understanding them is really understanding one question — does your traffic ride the public internet, protected by encryption, or a dedicated line that bypasses it entirely? VPN Gateway: an encrypted tunnel over the internet Microsoft's description is exact: Azure VPN Gateway "can be used to send encrypted traffic between an Azure virtual network and on-premises locations over the public Internet." Your traffic still travels the ordinary internet, but inside an IPsec/IKE tunnel, so it is private even though the road is shared. It comes in a few shapes: site-to-site (your datacenter's VPN device to Azure), point-to-site (an individual remote worker to the VNet), and VNet-to-VNet . It is quick to stand up, needs no third party, and is inexpensive — the pragmatic default for dev/test and small-to-medium production links. ExpressRoute: a private, dedicated circuit ExpressRoute takes the other road entirely. It "lets you extend your on-premises networks into the Microsoft cloud over a private connection with the help of a connectivity provider." The defining fact: because ExpressRoute connections do not go over the public internet , they offer "more reliability, faster speeds, consistent latencies, and higher security than typical connections over the internet." You are not tunnelling through shared roads; you have a private rail line into Microsoft's network, arranged through a connectivity provider. That extra reliability and consistency costs more and takes longer t

2026-08-27 原文 →
AI 资讯

RFLCT: Bringing Runtime Type Metadata to TypeScript 7

If you've built large-scale applications in TypeScript, chances are you've used a Dependency Injection (DI) container. As the creator of InversifyJS, I've spent years thinking deeply about inversion of control, decoupling, and how to make enterprise patterns feel natural in TypeScript. But for all those years, there has been a glaring elephant in the room: our heavy reliance on experimentalDecorators and emitDecoratorMetadata . These compiler flags have served us well, but they are exactly that— experimental . They tie us to legacy decorator implementations, require specific compiler configurations, and often feel like a magic black box that doesn't perfectly align with modern build pipelines. I've spent a lot of time recently thinking about how we could finally drop these flags entirely while keeping the developer experience pristine. With the release of TypeScript 7, I'm thrilled to introduce the solution: 🪞 RFLCT . What is RFLCT? RFLCT is an ahead-of-time (AOT) reflect metadata injector for TypeScript 7. It injects design:symbols and design:arguments directly at build time. Zero decorators. Zero emitDecoratorMetadata . It integrates seamlessly with virtually any build tool (Vite, Rollup, webpack, esbuild) via unplugin , or you can use the built-in CLI using the TypeScript 7 API for standalone tsgo projects. Let's look at how it actually feels to write code with RFLCT. The Magic: Before and After With RFLCT, you annotate the types you want to expose to your runtime metadata using a special Reflect<T> wrapper type. What you write: import { Reflect , resolve } from " rflct " ; interface Shape { sides : number ; } class Polygon { constructor ( public shape : Reflect < Shape > , public label : Reflect < string , { optional : true } > ) {} } // resolve<T>() → the runtime identity of T (Symbol for interfaces, class for classes) container . bind ( resolve < Shape > ()). to ( Polygon ); What RFLCT compiles it to: Notice how the interfaces are safely converted into global

2026-08-27 原文 →
开发者

Blue-green deployment that left the old environment running for weeks, doubling infrastructure cost

The deploy worked. The bill doubled. The blue-green cutover went perfectly. Traffic shifted to green, health checks passed, the team signed off, and moved on. It was one of those rare deployments that goes exactly as planned. Six weeks later, a cost anomaly surfaced in the monthly AWS review. Infrastructure spend had been running at roughly double what it should have been since the deployment date. Every EC2 instance, every RDS node, every load balancer from the blue environment was still running. Serving zero traffic. Billed at full price. For six weeks. Nobody had decommissioned it because nobody owned it after cutover. The team that ran the deployment assumed operations would clean it up. Operations assumed the team that deployed it would tear it down. The blue environment sat in a perfect ownership gap, healthy and idle and expensive, while both teams closed their tickets and moved on. This is the part blue-green deployment guides don't emphasize enough. The strategy is excellent for zero downtime releases and instant rollback capability. The rollback window is the dangerous part. It's open-ended by default, which means the old environment stays alive until someone makes a deliberate decision to shut it down. That decision requires ownership, and ownership requires someone to be responsible for it after the deployment is considered done. The fix is treating decommissioning as part of the deployment itself, not cleanup that happens afterward. Tag every blue environment resource at launch with a TTL: aws ec2 create-tags \ --resources i-1234567890abcdef0 \ --tags Key = DeploymentColor,Value = blue \ Key = CutoverDate,Value = 2026-01-14 \ Key = TTL,Value = 2026-01-21 Then wire Cost Anomaly Detection to alert when a specific environment tag is still generating spend past its TTL. The old environment doesn't get to become invisible just because traffic moved away from it. The deeper issue is that blue-green deployments create a window of parallel infrastructure that m

2026-08-27 原文 →