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
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
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
AI 资讯
Best Enterprise AI Gateway for LLM Cost Optimization in 2026
The first time you deploy an LLM application, cost usually isn't the biggest concern. You have one...
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
AI 资讯
The agent posted successfully. To the wrong account.
Back in July I wrote about what it takes to wire an AI agent into social platforms: six OAuth flows,...
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
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
AI 资讯
AI Dev Weekly #23: Qwen4 Architecture Preview, GPT-5.6 Lands in Kiro, Gemini Takes On Whisper
AI Dev Weekly is a Thursday series where I cover the week's most important AI developer news, with my...
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
开发者
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
AI 资讯
Building Local-First Web Apps: Parsing HTML and PDFs to Markdown in the Browser
Local-first and privacy-focused web utilities are having a massive comeback. With browser engines becoming faster and WebAssembly/Web Workers maturing, there is rarely a reason to push sensitive user documents to an external backend for simple conversions. While building MD-Convert (a zero-upload document to Markdown converter), I explored how to parse real-world documents into clean Markdown entirely on the client side. Here is a breakdown of the core architecture and libraries that make purely in-browser document processing possible. 1. Converting Web Articles with Readability + Turndown Converting messy web markup into clean Markdown involves two distinct steps: Content Extraction: Stripping ads, navbars, sidebars, and trackers. HTML-to-Markdown Transformation: Translating semantic DOM nodes into markdown tokens. Mozilla’s @mozilla/readability paired with turndown is an incredible combination for this: import { Readability } from ' @mozilla/readability ' ; import TurndownService from ' turndown ' ; function htmlToCleanMarkdown ( rawHtmlDocument , sourceUrl ) { // 1. Extract pure article content const reader = new Readability ( rawHtmlDocument ); const article = reader . parse (); if ( ! article || ! article . content ) { throw new Error ( ' Unable to extract main content ' ); } // 2. Initialize Turndown const turndownService = new TurndownService ({ headingStyle : ' atx ' , codeBlockStyle : ' fenced ' }); // Ensure image URLs remain absolute turndownService . addRule ( ' absoluteImages ' , { filter : ' img ' , replacement : ( content , node ) => { const src = node . getAttribute ( ' src ' ); const alt = node . getAttribute ( ' alt ' ) || '' ; if ( ! src ) return '' ; try { const absoluteUrl = new URL ( src , sourceUrl ). href ; return `\n\n` ; } catch { return `\n\n` ; } } }); return turndownService . turndown ( article . content ); } Offloading Heavy PDF Parsing to Web Workers Parsing large PDFs using pdf
AI 资讯
Day 32: Rebase Replays Your Commits, and a Restore Inherits Everything You Don't Override
Today's two tasks are both about a new base. A feature branch that needs to sit on top of a master that has moved. A database instance that needs to come back from a snapshot taken when things were fine. In each case, the interesting question is the same: what carries over, and what do you have to say out loud? One Git task, one AWS task. Rebase a feature branch onto master without creating a merge commit, then snapshot an RDS instance and restore it into a new one. The tasks come from the KodeKloud Engineer platform. Rebase: not moving commits, replaying them The requirement was specific, and the specificity is the lesson. A developer's feature branch was behind master. Bring it up to date without losing any feature work, and without a merge commit. That second clause rules out git merge master . Merge joins two histories and records the join, which is the merge commit. Rebase does something else entirely. cd /usr/src/kodekloudrepos/media git branch git log --oneline --graph --all --decorate git checkout feature git rebase master git log --oneline --graph --decorate Git's own documentation describes what happens under git rebase master : it lists the commits on your branch that are not on master, checks out master, and then replays each of your commits on top of it, one at a time, in a way it compares to running git cherry-pick for each one. Replays. Not moves. Every commit that comes out the other side has a new hash, because a commit's identity includes its parent, and the parent is different now. Your work is preserved, the commits carrying it are not the same objects they were. That is exactly why there is no merge commit. Rebase does not join two histories, it rewrites yours so it looks like it was always based on master's current tip. You get a straight line, at the cost of a history that is no longer a record of what actually happened. Two things I had to be deliberate about. Direction. Rebase applies to the branch you are standing on and takes the branch yo
开发者
I Built a Discord Server Discovery Platform
I Started Building a Discord Server Directory I’ve spent a lot of time around Discord communities, and one thing has always bothered me. Finding a good Discord server is harder than it should be. There are thousands of communities for gaming, anime, roleplay, technology, social groups and pretty much every niche you can think of. But finding the right one usually means jumping between invite links, old posts, server lists and search results. At some point I thought, why not build a better way to discover them? That’s how I started working on Dizord. The first version was pretty simple. I wanted a place where a server could be listed, people could discover it, and everything could be organized around interests instead of just one giant list of servers. Then the project started getting bigger. More servers meant more categories and tags. More tags meant better search and filtering. Server information changes constantly, so keeping listings updated became another problem to solve. I’m building the backend with Laravel and working with the Discord API to handle server information and synchronization. There are also a lot of small things behind the scenes that aren't obvious when you simply open a server listing page. One of the things I'm currently working on is making discovery better for smaller communities. A server shouldn't need tens of thousands of members just to be discoverable. The goal is pretty simple: Make it easier to find a Discord community you'll actually want to stay in. The project is still evolving, but the current version is live: https://dizord.com I'm still experimenting with search, categorization, server activity and ways to make a large directory useful instead of overwhelming. If you're building a directory, marketplace, or any project with thousands of constantly changing pages, I'd also be interested in hearing how you handle discovery and indexing at scale.
AI 资讯
An API that returns 200 and does nothing is worse than one that returns an error
I cross-post my articles to dev.to. Looking at the numbers, the posts tagged agents were getting traffic and the one without it had a single view in twenty hours. Obvious fix: add agents to that post. I sent a PUT updating the tags. The response was 200. I opened the post. The tags were unchanged. Three requests, three 200s, three identical responses Assuming I'd malformed the request, I ran the smallest test I could: three PUTs to the same article, sending agents , then python,agents , then the original tags. All three returned 200. All three returned byte-identical bodies — the tags the post was created with. The truth: dev.to tags are immutable after publish, and the API silently ignores the field. Not a 403 saying you can't do that. Not a 422 saying the field is read-only. A 200, and then nothing happens. That one field made me wrong twice The first time was the day before. I'd sent 4 tags and gotten 3 back. My conclusion: dev.to caps tags at 3. That conclusion is entirely reasonable. You send four, you get three, what else would it be? I was confident enough to write MAX_TAGS = 3 into a script comment as an established fact. What actually happened: the tags field was never applied at all. What came back were the three tags from creation time. It had nothing to do with a cap. I could have sent one tag or ten and gotten the same three. One silently ignored field, two wrong conclusions in two days, and I committed one of them to source control as documentation for my future self. That's the real cost. Not the failed request — the false fact I wrote down as knowledge. Why 200 is more dangerous than an error An error interrupts you . It forces a stop, and it usually tells you something true. Even when the message is imprecise, "this did not work" is accurate information. A 200 doesn't interrupt you. You tick the step off and move on. You proceed on a false premise, believing you verified it. Going back through my ops log, this failure mode shows up more than once. A
AI 资讯
The Bug Class AI Coding Agents Keep Introducing (and How We Started Catching It in CI)
The pattern AI coding agents are good at producing a diff that works in the narrowest sense — the function still returns what the test expects. What they're not reliably good at is preserving properties nobody wrote a test for in the first place. The two we kept running into: an authorization check quietly dropped during an agent-driven refactor (nothing failed, because no test covered who was allowed to call the route — only that the route worked), and a rewritten query that behaved fine against a small dev dataset and full-table-scanned the moment it hit production data. Neither shows up in CI as it exists today. Both show up in code review only if the reviewer happens to look at exactly the right five lines out of a few hundred. What we built Agent Code Merge Gate is a free GitHub Action, now live on the GitHub Marketplace , that runs on every pull request and scans the diff specifically for those two regression classes. It runs an offline heuristic pass (fast, no external call) plus one AI-backed pass for a short Executive Summary, and posts a single comment back to the PR that updates on every push rather than piling up duplicates. Deliberately narrow scope — it's not trying to be a general linter. It covers the two failure modes we found ourselves manually re-checking for once AI-generated PRs became the majority of our merge volume. Wiring it into CI Three lines in a workflow file: - name : Agent Code Merge Gate uses : avalonlabs-platform/agent-code-merge-gate@v1.0.0 ``` { % endraw % } No signup and no config needed for the default behavior. Two inputs worth knowing about : { % raw % } `fail-on-critical : true ` turns a CRITICAL finding into an actual failed check instead of just a comment, and `comment-on-pr : false ` if you'd rather build your own notification from the raw `status` output. ## What's next Right now it's diff-scoped — it sees what changed in this PR, not the whole repo's history of how that code got there, which limits how much context it
开发者
I Spawned 1000000 Goroutines. Here's Where 13 GB of RAM Went.
Ask any Go developer what a goroutine costs and you'll get the same answer with the exact byte count:...
创业投融资
Medical device maker Boston Scientific says a cyberattack is causing a ‘global disruption’ to its operations
The company won't say if medical devices are affected or if any customer data was exfiltrated.
科技前沿
The Porsche 911 GT3 Touring punches above its weight class
The "everyday" GT3 delivers, despite looming regulations and an ever-inflating price tag.
AI 资讯
Apple announces September iPhone launch event
Apple's next launch event will take place on September 9th at 1PM ET. Invites to the event, which has a "Surprise and shine" tagline, were sent out on Wednesday. The event will take place at the Steve Jobs Theater in Apple Park, but there will also be a livestream on Apple's website. September's show could […]