AI 资讯
Cpynet a pastebin you talk to with curl, that forgets everything you send it
A zero-dependency, single-file Go pastebin built for terminals — burn-after-read by default, two independent encryption layers, and a curl one-liner instead of a login form. I keep ending up in situations where I need to move a small piece of text — a log snippet, a password, a container's stdout — from one machine to another, and the clipboard just isn't there. SSH session on a remote box. A locked-down corporate laptop that won't let me touch the OS clipboard at all. A container with no shared volume and no browser. Slack is right there, but pasting a database password into a channel that's archived forever is a special kind of bad idea. So I built CPYNET — a paste-sharing tool with exactly one interface that matters: curl . echo "hello world" | curl --data-binary @- https://cpynet.com/ # https://cpynet.com/482913 curl https://cpynet.com/482913 # hello world That's the whole thing. No account, no API key, no clicking around. Two curl calls and you've moved text between two machines that have nothing in common except a network path. Burn-after-read, actually The paste above is gone the instant that second curl runs. Not "gone in 24 hours" — gone the moment it's read , whether that's one second later or one minute later. Read it twice (even from the same machine) and the second request gets a plain 404 . It also auto-expires on a timer (2 minutes by default) even if nobody ever reads it, so an unread secret doesn't just sit there. None of this lives on disk. It's a Go map behind a mutex, in memory, for the lifetime of one process. Restart the server and every paste that hasn't been read yet is just... gone. That's not a limitation I'm working around — it's the actual point. A "burn after read" tool that persists to disk somewhere you're not thinking about isn't really burning anything. The shell functions, if you don't want to remember the curl flags curl -s https://cpynet.com/install.sh -o install.sh && bash -n install.sh && . install.sh That wires up two functions
AI 资讯
A backup you haven't restored isn't a backup
Migrating from MongoDB Atlas to a self-hosted replica set bought us control and cut our bill. It also quietly removed something we had stopped thinking about: Atlas had been taking continuous backups for us the entire time. After the migration, production data for Prochesta lived in /var/db/mongo on a single VPS. No snapshots. No off-box copy. A rm -rf , a bad migration script, or a dead disk would have been the end of it. We had written "backups" as a follow-up task in the migration spec, which is the engineering equivalent of a sticky note on a bank vault. The requirement we actually cared about was narrower than "back up the database". Most real-world data loss at our scale isn't hardware failure — it's a deploy that writes garbage, or someone running an update without a filter. Recovering to last night doesn't help when the damage happened at 14:20 and you noticed at 14:50. We needed to recover to an arbitrary moment , not to a nightly snapshot. The constraint nobody mentions: Community has no $backupCursor We chose Percona Backup for MongoDB (PBM), and immediately hit the limitation that shapes every decision downstream. PBM offers physical backups — fast file-level copies that restore in minutes and barely touch the running server. They work by opening a backup cursor via the $backupCursor aggregation stage. That stage exists in Percona Server for MongoDB and in MongoDB Enterprise. It does not exist in MongoDB Community, which is what the official mongo:8.0 image ships. So on Community, PBM gives you logical backups only: every document read out through mongod , compressed, and shipped off-box. Two consequences, both accepted deliberately rather than discovered later: Backups cost CPU on the primary — and with a single-member replica set there's no secondary to offload the read to. Restores insert documents and rebuild indexes, so restore time grows with data size much faster than backup time does. At our current size that's minutes, not hours. It's also the t
AI 资讯
AmaliTech Apprenticeship Program (AAP) (AAP)
AmaliTech Apprenticeship Program (AAP) launched in November 2025, with its first cohort starting on November 17th, 2025. It is self-paced, meaning apprentices move through the curriculum at their own speed rather than following a fixed lesson-by-lesson schedule, though attendance in the office is still required. It offers 5+ specializations, including Fullstack Development (Node.js/NestJS and React/Next.js or Angular), Python Backend & AI App Development, Backend Development with Java, Data Engineering, DevOps, and Quality Assurance. There are two entry paths, entry-level and mid-level, based on experience, and each spends a different amount of time in the program: entry-level apprentices spend 6–9 months, while mid-level apprentices spend 4–6 months. The program is intense: apprentices are required to be in the office 10 hours a day, Monday through Friday. In return, it offers solid compensation. Entry-level apprentices receive a stipend of 250k+ RWF, and mid-level apprentices receive 500k+ RWF. That's the program itself. So how do you actually join? Eligibility The biggest requirement: since this is an in-person program, you need to already be based in Rwanda or be willing to relocate. A background in software development. The Application Process Apply. Applications open every three months. Cohorts have run in November 2025, March 2026, June 2026, and September 2026, so you can expect the pattern to continue. Screening, then two assessments. If you pass the screening stage, you move on to: General Coding Assessment (GCA): the harder of the two, but manageable with preparation. It's done on CodeSignal , either in person or online. To prepare, practice DSA questions on competitive programming sites like LeetCode , Codewars , and CodeChef for 1–2 weeks, and you should be in good shape. Cognitive Test: taken the same day as the GCA, this evaluates problem-solving, pattern recognition, numerical analysis, and similar skills. Preparation helps here too. Watching a few Y
开源项目
GitHub doesn't retry webhooks. So I gave my tunnel a database.
Built solo over a weekend for the WeMakeDevs × Zerops challenge. There's a live gateway you can poke...
AI 资讯
AI Didn't Replace My DevOps Workflow. It Shortened the Path to a Hypothesis.
How an alert, ten browser tabs, and a Slack ping actually get resolved when AI is in the loop — and where I still don't trust it. An alert fires. I open Grafana. Then CloudWatch. Then the logs. Then kubectl describe on the pod that's misbehaving. Then GitHub, to see what merged. Then Argo CD, to see what actually rolled out. Ten tabs in, trying to hold six timelines in my head at once, someone drops into the channel: Do we know what happened yet? That moment is the real job. Not the syntax. Not remembering the exact kubectl flag. The job is correlating scattered signals fast enough to form a hypothesis worth testing. That's the part where AI has changed how I work. It didn't take the troubleshooting away from me. I'm still doing all of it. It just shortened the gap between "something is wrong" and "this is probably where I should look." I don't use AI as a replacement for understanding Kubernetes, AWS, Terraform, Linux, networking, databases, or CI/CD. I use it as another tool in the workflow, one that helps me get from a problem to a testable hypothesis faster. My AI usage today broadly splits across three areas: ChatGPT — communication, research, reasoning, and technical analysis Claude and Claude Code — coding, Kubernetes, scripts, configurations, and troubleshooting AWS DevOps Agent — AWS infrastructure investigation, resource analysis, troubleshooting, and optimization Each tool has a slightly different role. The part that actually matters isn't having access to AI. It's knowing where it's useful, what context to give it, and when its output needs to be challenged. None of them makes a production decision for me. One habit before I get into the tools: I'm careful about what I paste into any of them. Config with real hostnames, account IDs, or anything secret-shaped stays out. ChatGPT: the part of DevOps nobody warns you about People underestimate how much of this job is communication. I'll finish a technical investigation and then have to explain it — to a deve
AI 资讯
GGUF vs GPTQ vs AWQ: Which Quantization Format Should You Actually Use?
Running open-source Large Language Models (LLMs) used to be a luxury reserved for developers with enterprise-grade server rooms. If you didn't have dual A100 GPUs sitting under your desk, running a modern 8B or 14B parameter model was a one-way ticket to Out-Of-Memory (OOM) crashes and frozen systems. Then came quantization. By compressing 16-bit floating-point weights (FP16) down to 4-bit or 8-bit integers, quantization slashes the VRAM footprint of LLMs by 70% or more, often with barely noticeable drops in accuracy. But as you browse Hugging Face for a model, you are immediately hit with a wall of acronyms: GGUF, GPTQ, and AWQ. Which format actually fits your hardware? Which one delivers the fastest tokens-per-second? And how do you generate these files without melting your local machine? Let's break down the definitive differences so you can choose the exact format your pipeline needs. 1. GGUF: The King of Local Hardware and CPU Offloading Developed by the team behind llama.cpp, GGUF (GPT-Generated Unified Format) completely revolutionized local LLM execution. How it works: Traditional formats require a powerful GPU to load a model. GGUF changes the rules by allowing CPU offloading. If a model requires 12 GB of VRAM but your graphics card only has 8 GB, GGUF splits the layers: it loads 8 GB into your GPU and shunts the remaining 4 GB to your system RAM and CPU. The trade-off: While running models on system RAM is significantly slower than running them purely on a graphics card, GGUF ensures the model actually runs. It turns a guaranteed system crash into a functional, runnable local AI. If you have a powerful GPU, GGUF can also run 100% on the graphics card for blistering speeds. Hardware: Apple Silicon MacBooks (M1/M2/M3), laptops with consumer Nvidia cards (e.g., RTX 3060/4060), or setups without a dedicated GPU. Use Case: Local application development, hobbyist exploration, and offline edge computing. 2. GPTQ: Enterprise-Grade Speed for Pure GPU Pipelines GPTQ
AI 资讯
Cedar could stop one bad tool call. Dogwood stops bad sequences.
AWS launched Dogwood this week — an open-source policy language (Apache 2.0) for AI agent runtime verification. It extends Cedar, AWS's existing authorization language (now a CNCF sandbox project), with something Cedar fundamentally can't do: reason about sequences of actions over time. "Point-in-time decisions make sense for many forms of access control, but when agents compose multiple actions into longer workflows, the sequence itself becomes something teams want to govern." That's the gap Dogwood fills. What Cedar couldn't do Cedar is stateless. You give it a request — principal, action, resource, parameters — and it returns allow or deny. Given the same request, Cedar always returns the same answer, regardless of what happened five minutes ago. That's a useful property for analysis, but it's a blind spot for agents. Consider: an agent is restricted to transferring no more than $5,000 per hour. If Cedar only evaluates the current request against completed transfers, the agent can fire off three concurrent $2,000 requests before any of them finish. Each looks fine in isolation. The total blows the limit. Dogwood has the event history. It counts all transfer requests — including those currently in-flight — so the third $2,000 request gets denied even before the first two complete. What Dogwood adds Dogwood introduces temporal conditions that examine earlier tool calls and their results. You can: Check whether an event occurred — e.g., was approval granted for this exact stock/quantity in the last hour? Count calls in a time window — rate limiting across concurrent requests Count distinct values — e.g., how many unique payment recipients this session Sum values — total transferred, total refunded The stock trading example from AWS is the clearest illustration: an agent may only sell shares if an approval tool returned a positive response for that stock and share count within the previous hour. That approval is a separate event the policy engine finds in the agent's
AI 资讯
CPU utilization lies: autoscaling a single-threaded service
The service was slow. Not down, just slow: p95 latency climbing well past where users notice, requests piling up, the kind of degradation that generates support tickets instead of alerts. And the autoscaler, the whole point of which is to add capacity when a service is under strain, sat there doing nothing. The metric it was watching said everything was fine. Average CPU utilization on the tasks was hovering around 30 percent, nowhere near the scale-out threshold. The dashboard was calm. The users were not. Both were right, and the gap between them is one of the most common autoscaling traps on a container platform. This is the first article in a series on running a multi-tenant SaaS on AWS at team scale. It is about a metric that lies, quietly, by design. Why 30 percent CPU meant 100 percent busy The service was a single-threaded application. A Node.js API, in this case, but the same is true of any process that does its real work on one thread: a classic Python or Ruby worker, most single-process runtimes. A single-threaded process can, by definition, saturate exactly one CPU core. The task it was running on had four vCPUs. So the arithmetic that matters is brutally simple: one core fully pegged / four vCPUs on the task = ~25% task-average CPU At full saturation, the busiest that process can ever make the task look is about 25 percent. Add a little async I/O overhead spread across the runtime and you land around 30 percent. That is not a service with headroom. That is a service redlining on the only core it can use, while three cores sit idle and drag the average down to a number that reads as "barely working." The autoscaling policy was tracking average CPU across the task's cores. For a workload that can only ever use one of them, that average is not a measure of load. It is a measure of load divided by four. The metric was answering a different question This is the real lesson, and it is not specific to AWS or ECS. Average CPU utilization answers "how much of th
开发者
Hey everyone! I recently wrapped up a project migrating 6 separate Go microservice repositories into a unified monorepo setup. I documented the architecture decisions, pipeline setup, and lessons learned here.
Multi-Repo to Monorepo: How I Automated 6 Go Microservice Releases and Then Made It 15x Faster Amandeep Singh Amandeep Singh Amandeep Singh Follow Aug 7 Multi-Repo to Monorepo: How I Automated 6 Go Microservice Releases and Then Made It 15x Faster # go # devops # automation # monorepo 6 reactions 1 comment 10 min read
AI 资讯
AI Can Write Tests Faster Than Your Team Can Understand Them
AI coding tools have solved one problem remarkably well: They can produce code extremely quickly. That sounds obviously good. And most of the time, it is. But software development has never really been constrained by how fast we can type. The expensive part comes later. Understanding the code. Reviewing it. Debugging it. Changing it six months later when the person—or model—that wrote it has forgotten why it exists. Test automation is where this becomes especially interesting. Generating the Test Is the Cheap Part You can ask an AI coding assistant: Write Playwright tests for our signup, login, checkout, password reset, dashboard, invoices, settings, and admin pages. And a few minutes later you might have hundreds or thousands of lines of test code. It feels like incredible leverage. Until the suite starts failing. That’s the argument behind looking at the hidden cost of AI-generated test code . Generation cost has collapsed. Maintenance cost hasn’t. In some cases, AI actually increases it because you now have more code than your team would have written manually. AI Pull Requests Need Different Review There’s another subtle problem. Humans tend to judge large AI-generated pull requests differently. When someone on your team writes 80 lines, you probably read them. When an AI assistant generates 1,800 lines? You skim. You look at the filenames. You check whether CI is green. Merge. That’s dangerous for normal application code and potentially worse for test code because a bad test can happily pass for months. There are good ideas in this guide to testing AI coding assistant pull requests , but the bigger principle is simple: AI-generated tests need validation just like AI-generated product code. “Generated successfully” does not mean “tests the right thing.” Agents Add Another Failure Mode Now we’re moving from AI that writes test code to AI that actually decides what actions to take. That introduces a new question: What if the model chooses the wrong tool? An agent m
AI 资讯
Kubernetes Secrets Are Just Base64 Not Encryption. Here's What That Actually Means
If you've run Kubernetes for more than a day, you've seen this: apiVersion : v1 kind : Secret metadata : name : db-credentials type : Opaque data : username : YWRtaW4= password : c3VwZXJzZWNyZXQ= And somewhere in the back of your mind you filed it under "encrypted credentials." It isn't. Those values are Base64, and Base64 is encoding, not encryption. YWRtaW4= is just admin written in a different alphabet — reversible instantly, by anyone, with no key. This trips up an astonishing number of teams, so let's clear it up for good. Prove it in one command kubectl get secret db-credentials -o jsonpath = '{.data.password}' | base64 --decode # supersecret No key. No password. No "decryption." Base64 is a binary-to-text encoding — its entire job is to represent arbitrary bytes using a safe 64-character alphabet so they survive transport and storage in text-based systems (etcd, YAML, JSON, HTTP headers). Kubernetes encodes Secret data values purely so binary values (certs, keys, gzip blobs) can live inside a YAML/JSON object. That's it. Security was never the point. If you want to eyeball a whole Secret at once instead of decoding fields one by one, I built a small in-browser tool for exactly this — paste the YAML and it decodes every data: value locally (nothing is uploaded): Kubernetes Secret Decoder . (Disclosure: it's my free, no-ads tool.) data vs stringData A quick related gotcha: data expects Base64 , but stringData expects plain text and Kubernetes Base64-encodes it for you on write: stringData : password : supersecret # plain text; k8s encodes it into data.password Both end up identically un-secret at rest. So what actually protects a Secret? Base64 gets you nothing here. Real protection is layered: Encryption at rest for etcd — configure a KMS provider (AWS/GCP/Azure KMS) or at minimum aescbc / secretbox via an EncryptionConfiguration . Without this, Secrets sit in etcd Base64-only. Sealed Secrets (Bitnami) — encrypt secrets before they hit Git; only the in-cluster
AI 资讯
Stop Chasing Symptoms: How We Built an Autonomous Root Cause Analysis Engine in Rust 🦀
It’s 2:15 AM. Your phone buzzes aggressively. 🚨 You jump out of bed, open your laptop with half-closed eyes, and join an emergency incident response call. Your team’s Slack channel is exploding: ⚠️ [ALERT] Payment API 500 Error Rate > 15% ⚠️ [ALERT] Redis Latency Timeout (>5000ms) ⚠️ [ALERT] Node-04 CPU Saturation (98%) You spend the next 2 hours manually connecting the dots: querying Prometheus metrics, scrolling through endless Loki logs, cross-referencing Tempo traces, and checking recent ArgoCD deployments. Eventually, you uncover the truth: Deployment #218 , pushed right before midnight, introduced a subtle memory leak that triggered GC pressure, spiked CPU, starved the Redis connection pool, and knocked down the Payment API. Sounds familiar? 😅 💥 The Problem: Observability Shows Symptoms , Not Causes Modern observability tools like Grafana, Prometheus, Loki, and Jaeger are fantastic at collecting metrics, logs, and traces. But they suffer from one fundamental design limitation: They tell you WHAT is breaking, but leave you to figure out WHY it broke. When a microservice fails in Kubernetes, it triggers a domino effect ( cascading failure ): Deployment #218 (Memory Leak) │ ▼ Garbage Collection Pressure │ ▼ CPU Saturation (98%) │ ▼ Redis Connection Timeout │ ▼ API Gateway Retry Storm │ ▼ Payment Service Down (HTTP 500) Traditional alerting floods you with alerts for the bottom 4 nodes (the symptoms), leaving SREs and DevOps engineers stuck sifting through noise during high-stakes outages. 💡 Introducing IRCAE: Autonomous Root Cause Engine To solve this, we are building IRCAE (Intelligent Root Cause Analysis Engine) —an open-source, enterprise-grade platform designed to turn raw telemetry into autonomous causal reasoning . Instead of asking SREs to correlate telemetry manually, IRCAE automatically answers: "Why did the system fail?" in less than 10 seconds. 🌟 Key Highlights 🚀 Written in Rust (Axum + Tokio) : Built for high-throughput, near-bare-metal performance wi
AI 资讯
Why AI Applications Should Submit Workloads, Not Select GPUs
A developer is building an AI application that needs to run a GPU-backed inference job. The first implementation looks straightforward: # Simplified example provider = CloudGPUProvider ( api_key = API_KEY ) instance = provider . launch_instance ( region = " us-east " , instance_type = " gpu.large " , gpu_model = " specific-gpu-model " , image = " registry.example.com/inference:v1 " , ) provider . run_command ( instance_id = instance . id , command = " python inference.py --input /data/request.json " , ) It works. Then the selected region runs out of capacity. The developer adds another region. The second region does not offer the same instance type, so the application needs a hardware-specific branch. Another provider has available GPUs, but its API uses a different lifecycle model. One provider expects the application to manage virtual machines. Another starts containers directly. A third exposes jobs, but returns logs and artifacts through separate services. The original inference feature gradually becomes an infrastructure orchestration system. Application code now contains: Provider credentials Region-selection logic GPU-model mappings Capacity checks Instance lifecycle management Startup polling Retry rules Fallback providers Log collection Artifact retrieval Cleanup procedures The application began with a business requirement: Run this AI workload. It ended with infrastructure-specific code describing exactly where and how the workload should run. That is the wrong abstraction. AI applications should describe the workload they need executed. An infrastructure layer should decide how to satisfy that request. Instead of saying: Launch this exact GPU instance from this exact provider. Applications should be able to say: Execute this workload with these runtime, memory, latency, compatibility, and cost constraints. That shift—from instance provisioning to AI workload execution —removes infrastructure decisions from the application without pretending that hardware
AI 资讯
I Got the Internship Offer… and Then I Had to Say No.
A few days ago, I went for an internship opportunity that I was genuinely excited about. I had been looking forward to it for a long time. When I got the opportunity to attend a 3-day demo/trial period , I went in with a lot of excitement. I wanted to prove myself, learn as much as possible, and hopefully turn those three days into something bigger. And honestly, I gave it my best. I showed up, worked, learned, asked questions, and tried to contribute wherever I could. Then came the moment I had been hoping for. I received the offer letter. ❤️ For a moment, I was extremely happy. After being out of college and working hard to build my skills, finally getting an offer felt like a big step forward. But then I had to look at the practical side. The internship was work from office , and the stipend was ₹7,000/month . The biggest challenge was the distance. I live around 90 km away from the office. When I calculated the daily travel, food, and other expenses, I realized that accepting the internship would put a huge financial burden on me every month. And that was a very difficult realization. Because emotionally, I wanted to say: "Yes, I got an internship. Let's do this!" But practically, I had to say: "I can't afford this right now." So I rejected the offer. And honestly? It hurts. Not because the company did something wrong. Not because I didn't want to work. But because I finally got an opportunity I was excited about, gave it my best during the trial period, received the offer… and still had to walk away from it. I've been feeling pretty bad about it. There is always this thought in the back of my mind: "What if I had just accepted it?" But I'm also trying to remind myself that rejecting one opportunity doesn't mean I've failed. Sometimes an opportunity can be good and still not be right for your current situation. I'm taking this experience as a lesson: Getting an offer is not the final goal. Salary/stipend matters. Location and travel expenses matter. Your time ma
AI 资讯
AWS Route 53 — DNS Fundamentals, Hosted Zones, Routing Policies & Resolvers
Part of my AWS learning journey — transitioning from Systems Engineer to Cloud/DevOps. Route 53 is where networking meets the internet — how domain names reach your applications, how traffic gets distributed intelligently, and how AWS and on-premises networks resolve each other's names. 📋 Topics Covered # Topic Type 1 DNS Pre-Requisites — How DNS Works Concept 2 Complete DNS Resolution Flow Concept + Interview 3 What is Route 53 Concept 4 Hosted Zones — Public vs Private Concept + Lab 5 Hosted Zone ID Concept + DevOps 6 DNS Record Types and Use Cases Concept + Cert 7 NS and SOA Records — Auto-Created, Never Delete Concept + Interview 8 Alias Record — AWS-Specific Concept + Cert 9 Landing Zone — Brief Context Concept 10 Route 53 Routing Policies — All 8 Concept + Cert 11 Route 53 Traffic Policies Concept + DevOps 12 Route 53 Resolvers Concept + Interview 13 Inbound vs Outbound Resolver Endpoints Concept + Interview 14 Route 53 Forwarders Concept + Interview 15 Split-Horizon DNS Concept + Interview 16 Interview Questions Interview 17 Practice Tasks Practice DNS Pre-Requisites — How DNS Works DNS is the reason you type google.com instead of 142.250.195.46 . Before understanding Route 53, these fundamentals must be solid. Core Vocabulary Term What it means Domain Human-readable name — google.com , tejascloud.in IP Address Machine address — 54.21.11.90 — what computers actually use DNS The translation system — converts domain names → IP addresses TLD Top-Level Domain — the last part after the final dot TTL Time To Live — how long a DNS response is cached before re-querying Recursive Resolver Finds the answer for the client by querying other DNS servers, caches the result Authoritative DNS Server Stores the official DNS records for a domain — returns the definitive answer Common TLDs: .com → commercial · .org → organizations · .net → network · .in → India · .uk → United Kingdom · .edu → education · .gov → government The Complete DNS Resolution Flow This is the full journe
AI 资讯
A 200 From the Wrong System: How Two Pages Stayed Invisible for 17 Days
Two pages on my site went live on July 22. On August 8 they had zero impressions in Google. Not low. Zero, across three weekly exports. URL Inspection didn't say "crawled, not indexed." It said Google could not recognise the URL. Referring sitemap: none detected. Referring pages: none detected. Last crawl: not applicable. Never discovered. Seventeen days. The pipeline was green the entire time My deploy is a small chain: rsync the file, import it into MySQL, restart the service, ping IndexNow. Every step returned success. The last step returned 200 on every URL, every deploy, for three weeks. Here's what I'd never examined: IndexNow doesn't feed Google. It's Bing, Yandex, Seznam, Naver. My green light was real — it was just about a different search engine than the one whose console I was reading. That's the whole bug, and it isn't an SEO bug. It's the generic one: system A returns 200 → I conclude something about system B → nothing in the response object ever objected If you've ever read a webhook 202 as "the downstream processed it," or a CDN purge 200 as "the edge is cold," it's the same shape. What actually broke Search Console's Sitemaps report: Submitted: 2026-07-22 Last read: 2026-07-22 ← seventeen days ago Discovered: 101 URLs ← the file has had 117 for weeks The two pages went live on July 22 — the same day as the only read. Google fetched the sitemap and moved on, within hours of the file changing. Then nothing brought it back, because a sitemap changing on your server notifies nobody. There is no push. It's a pull-only resource with no cache invalidation, and if the consumer doesn't happen to return, your new URLs live in a document no one is reading. Resubmitting took two minutes. Read immediately, 117 URLs. So I wrote the check. It doesn't catch the bug. This is the part worth more than the fix. I wrote a post-deploy verifier. It does two things: // 1. every published, non-redirected page appears in the live sitemap const missing = published.filter((p) =
AI 资讯
Domain-Driven Infrastructure: Organize Your Terraform by Reason to Change
One morning, a new engineer on the team asked me a simple question. "The Lambda for the new notification feature — does it go under modules/ , or somewhere else?" I didn't have a good answer. We had a modules/lambda/ directory, so the obvious move was to put it there, and I nearly said so before something stopped me. The notification feature was part of the order workflow. Was this a reusable part, or a piece of the order domain? Two different questions were hiding inside one "where does it go?", and our directory structure couldn't tell them apart. The conversation ended the way these conversations always end. "Let's just put it in modules/lambda/ for now." The layout everyone uses You've probably seen this structure. Most Terraform repositories look like it: ├── modules/ │ ├── vpc/ │ ├── ecs/ │ ├── rds/ │ ├── iam/ │ └── lambda/ └── environments/ ├── dev/ └── prod/ It works. It plans, it applies, it looks organized. Nothing about it is wrong until the business asks for something. "Ship the new feature." "Traffic doubled, scale it up." "Compliance changed, revisit the permissions." Each request is one business change. And each one sends you into vpc/ , ecs/ , rds/ , iam/ , secrets/ , cloudwatch/ . Different requests, same sprawl. One reason to change, six directories to touch. Back when I worked this way, review time didn't go where you'd expect. Whether the change was correct was the easy part. The hard question was whether it was safe to apply, and nobody could answer that from the diff, so we asked whoever remembered what else depended on the security group being edited. Software design has a word for this: low cohesion. Things that change together are stored apart. We'd never accept this in application code. We learned — from decades of work on cohesion, coupling, and separation of concerns — to keep things that change together in one place. Somehow that vocabulary never made it down to our infrastructure repositories. This is not a Terraform problem. It is a de
AI 资讯
Docker for Beginners: Images, Containers, Ports, and Volumes Explained
Docker for Beginners: Images, Containers, Ports, and Volumes Explained If you've ever followed a programming tutorial and seen something like: docker run ... you've probably wondered: What exactly is Docker doing? I had the same question when I started learning Docker. At first, I thought Docker was simply a way to "run applications in containers." But there is much more to it. Once I understood four concepts — images, containers, ports, and volumes — Docker became much easier to understand. So let's break it down from the beginning. What Is Docker? Docker is a platform for building, packaging, and running applications in isolated environments called containers . The basic idea is simple: Package an application together with the things it needs to run, and make that package portable. For example, imagine you build a Python application. Your application might depend on: Python 3.12 FastAPI Uvicorn Several Python packages Environment variables Certain system libraries On your computer, everything works. Then someone else downloads your project. They install a different Python version. A package is missing. Something behaves differently. Now you have: "It works on my machine." Docker helps reduce this problem by allowing you to define the environment your application should run in. The Four Concepts You Need to Understand Before learning Docker commands, understand these four things: Docker Image ↓ Docker Container ↓ Ports ↓ Volumes Let's look at each one. 1. What Is a Docker Image? A Docker image is a packaged, read-only template used to create containers. Think of it like a blueprint. For example: Docker Image │ ├── Ubuntu ├── Python ├── Application code ├── Dependencies └── Configuration An image contains the instructions and filesystem needed to create a container. You can download images from container registries such as Docker Hub. For example: docker pull nginx This downloads the Nginx image. You can see your downloaded images with: docker images You might see s
AI 资讯
What Are Autonomous AI Agents? A Practical Guide for Developers
Most AI applications wait for a user to ask a question and then return an answer. Autonomous AI agents go further: they can interpret a goal , decide what steps are required, use external tools, evaluate the results, and continue working until the task is completed or human help is needed. For example, a chatbot can explain how to resolve a customer complaint. An AI agent can read the complaint, retrieve the customer's order, check company policy, prepare a response, update the support ticket, and request approval before issuing a refund. That ability to make decisions and take actions is what makes autonomous AI agents different from traditional chatbots and fixed automation. 1. What Is an Autonomous AI Agent? An autonomous AI agent is a software system that uses an AI model to pursue a goal with limited human intervention. It can understand instructions, create a plan, select tools, perform actions, observe the results, and adjust its approach when necessary. A typical agent can: Understand a high-level objective Break the objective into smaller tasks Choose which tools or APIs to use Retrieve relevant information Take actions in external systems Maintain context across multiple steps Evaluate whether each action succeeded Recover from some failures Stop, retry, or escalate to a human Autonomous does not mean completely independent or unrestricted. A well-designed agent operates inside defined permissions, policies, spending limits, approval rules, and stopping conditions. 2. How Autonomous AI Agents Work Most autonomous agents follow a continuous decision loop: Receive Goal ↓ Observe Context ↓ Create or Update Plan ↓ Choose a Tool ↓ Perform an Action ↓ Evaluate the Result ↓ Continue, Retry, Stop, or Escalate Suppose a user gives an agent this goal: Find three suitable meeting times with the product team next week and send invitations after I approve one. The agent may: Identify the required participants. Retrieve their calendar availability. Check working hours a
AI 资讯
The Headless Workspace: How Antigravity CLI Lowers the Neovim Learning Curve
A GUI IDE is great for local development, but it quickly falls apart when you transition to headless servers, low-power client machines, or remote clouds. If you pair an AI agent like Antigravity CLI with a native-first Neovim configuration, you can bypass complex setups entirely. Since the AI assistant is the one doing the heavy writing, refactoring, and saving of files, you don't need to be a Vim keyboard wizard to use Neovim. The editor simply becomes a fast, native terminal pane for inspecting the code and reviewing git diffs. By pairing the two, you can build a modern, high-performance workspace built on native features that runs perfectly in any terminal. Here is the backstory of how we ended up with this setup, and why going native-first in Neovim became our preferred remote development tool. 💻 The Backstory: From a Broken Screen to Ephemeral Cloud VMs My 10-year-old MacBook Pro recently had its screen break. It still works fine, but it is now permanently anchored to my desk with an external monitor. Buying a new laptop is too expensive right now, but I have an iPad that I use when traveling. To work from the iPad, I use Google Cloud Shell via the web browser. This allows me to write and inspect code using the Cloud Shell Editor and run Antigravity CLI . However, Cloud Shell has strict storage, memory, and CPU limits. As an Application Modernization, DevOps, and SRE developer, my projects are resource-intensive. I need to run multi-container environments like the Google Cloud Microservices Demo . Plus, next week I’m attending the Gemma Day Event hosted by the Google DeepMind team. This will be my first hands-on contact with Gemma, and after the event, I plan to continue testing how the model interacts inside a Kubernetes cluster, establishing observability for LLM-native metrics (like token throughput and response latency). I don't want to buy an expensive machine with a GPU just to test these setups. Instead, I want to spin up a GPU-enabled VM in Compute Eng