惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tenable Blog
MyScale Blog
MyScale Blog
罗磊的独立博客
Hugging Face - Blog
Hugging Face - Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
爱范儿
爱范儿
博客园 - 司徒正美
D
Darknet – Hacking Tools, Hacker News & Cyber Security
量子位
N
News | PayPal Newsroom
S
Secure Thoughts
酷 壳 – CoolShell
酷 壳 – CoolShell
L
LINUX DO - 热门话题
有赞技术团队
有赞技术团队
V
Visual Studio Blog
T
Tailwind CSS Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Project Zero
Project Zero
B
Blog RSS Feed
J
Java Code Geeks
Google Online Security Blog
Google Online Security Blog
Last Week in AI
Last Week in AI
Cyberwarzone
Cyberwarzone
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
小众软件
小众软件
博客园 - 【当耐特】
Latest news
Latest news
T
Threat Research - Cisco Blogs
aimingoo的专栏
aimingoo的专栏
博客园_首页
博客园 - 三生石上(FineUI控件)
Engineering at Meta
Engineering at Meta
D
Docker
Forbes - Security
Forbes - Security
Help Net Security
Help Net Security
Apple Machine Learning Research
Apple Machine Learning Research
P
Proofpoint News Feed
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
V2EX - 技术
V2EX - 技术
N
Netflix TechBlog - Medium
The Last Watchdog
The Last Watchdog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
Threatpost
Cloudbric
Cloudbric
T
The Exploit Database - CXSecurity.com
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 叶小钗
Webroot Blog
Webroot Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
I deployed 12 vibe-coded apps to production. The same 6 things broke every single time.
Chalom Ellez · 2026-05-20 · via DEV Community

Disclosure: I am a senior backend tech lead in Paris and I run HostingGuru, a small European PaaS. This article mentions HostingGuru once near the end. The content works on any platform you choose.

Last month, a non-tech founder messaged me at 23h on a Tuesday. Her Lovable-built waitlist had hit Product Hunt at noon Pacific, racked up 4,000 signups by dinner, and the dashboard was now returning a blank white screen. She had pushed nothing. Nothing changed. She also could not log in to her own admin panel.

I have seen this exact failure mode roughly 12 times in the last 8 months. Different founder, different tool (sometimes Lovable, sometimes Bolt, sometimes Cursor, sometimes Claude Code), same six holes. The code the model wrote was fine. Production exposed assumptions the model could not see.

This is a field guide to those six holes. If you have shipped (or are about to ship) anything you built with an AI coding tool, you will recognize at least three of them.

Why vibe-coded apps fail in production specifically

A coding model writes the code in front of it. It does not see your DNS, your env vars, your cold-start behavior, your database connection limits, your timezone, or the fact that your "production" environment is actually your laptop with ngrok pointed at it.

Models are also trained on a corpus where "it works locally" usually means "it works." For a side project on a single laptop, that is true. For a deployed app with real users on real networks across real timezones, it is wildly false. The model is not lying. It just has no production telemetry. You have to add that yourself.

Here are the six patterns. Each one I have personally pulled out of a vibe-coded codebase in the last year.

Pattern 1: The API key that shipped in the JS bundle

Roughly 7 out of 12 vibe-coded apps I audited had at least one API key directly in client-side code. The model put it there because the model was told "call the Stripe API from this React form." The model did not say "by the way, this key is now visible to every browser on Earth via View Source."

The tell: you grep the dist/ or .next/ build output for the first few characters of your key, and you find it.

# Run this against your built output before deploying
cd dist && grep -r "sk_live_" . || echo "Clean"
cd .next && grep -r "sk_live_" . || echo "Clean"

Enter fullscreen mode Exit fullscreen mode

Fix: every secret call goes through a backend route. The client sends a request to your server. Your server, holding the secret in an env var, calls the third party. Even for a static site, you can run a tiny serverless function or a single Express route for this. Costs nothing, takes 15 minutes.

If you only learn one thing from this post, learn this one. Leaked Stripe keys, leaked OpenAI keys, and leaked Resend keys cost real money and real customer trust. I have seen one founder rack up $1,800 in OpenAI charges in 11 hours because a leaked key got scraped off a GitHub mirror.

Pattern 2: The unbounded query that nukes the database

The model writes SELECT * FROM users WHERE org_id = ? and it works fine because in development you have 4 users. The same query in production, when your largest customer has 80,000 users, returns 80,000 rows over the wire, into your Node process, into JSON, and onto the network. Your API server's memory spikes. Your database connection pool gets exhausted. Your dashboard returns the blank white screen.

This is the most common Lovable / Bolt failure I see, by a wide margin.

The fix is paginate everything and put an upper bound on every query. Pick a default limit (50 is fine for most things), enforce it at the query layer, and only allow the client to ask for more in explicit chunks.

// Bad (what the model wrote)
const users = await db.query('SELECT * FROM users WHERE org_id = $1', [orgId]);

// Better
const limit = Math.min(parseInt(req.query.limit) || 50, 200);
const offset = parseInt(req.query.offset) || 0;
const users = await db.query(
  'SELECT * FROM users WHERE org_id = $1 ORDER BY id LIMIT $2 OFFSET $3',
  [orgId, limit, offset]
);

Enter fullscreen mode Exit fullscreen mode

While you are in there, add an index on the column you are filtering by. Most vibe-coded apps have zero indexes outside the ones the ORM created automatically on primary keys.

Pattern 3: The CORS wildcard that opens the front door

Every model I have worked with, when asked "I am getting a CORS error," will reliably suggest setting Access-Control-Allow-Origin: *. It removes the error. It also opens your API to every site on the public internet, which is a problem the moment you have a session cookie or an auth token.

The right answer is to whitelist your own domain (and your staging domain, and localhost:3000 for dev).

// Express
const allowedOrigins = [
  'https://yourapp.com',
  'https://staging.yourapp.com',
  'http://localhost:3000',
];

app.use(cors({
  origin: (origin, callback) => {
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  },
  credentials: true,
}));

Enter fullscreen mode Exit fullscreen mode

If your AI tool wrote app.use(cors()) with no options, you have a wildcard. Audit it.

Pattern 4: The timezone mismatch nobody notices until billing

Your server is on UTC. Your dev laptop is on Paris time, or PST, or Bangalore. Your users are everywhere. The model probably wrote new Date() in a dozen places and the dates look "correct" to you because you are the only person who has looked at them.

Then a customer in Tokyo says "your invoice has the wrong month" and you discover that your billing cron, which runs at "midnight" your time, actually fires on the wrong day for half your customer base.

Three rules that catch most of these:

Store everything in UTC in the database. Always. ISO 8601, with the Z. If your ORM is doing anything else, fight it.

Display in the user's timezone, computed on the client side or with the user's stored preference. Never assume server-local.

For scheduled jobs (billing runs, daily digests, weekly emails), use cron-style scheduling that is explicit about timezone, or schedule them in UTC and document the offset.

// Use Intl on the client for display
const userTz = Intl.DateTimeFormat().resolvedOptions().timeZone;
const formatted = new Intl.DateTimeFormat('en-US', {
  timeZone: userTz,
  dateStyle: 'medium',
  timeStyle: 'short',
}).format(new Date(isoStringFromAPI));

Enter fullscreen mode Exit fullscreen mode

This bug compounds with Pattern 2. If you have an unbounded query plus a bad timezone, you can ship invoices in the wrong currency to the wrong country with no audit trail. I have seen it.

Pattern 5: The file path that works on your laptop and nowhere else

fs.readFileSync('./data/seed.json') works perfectly when you run npm start from your project root. It explodes when your deploy runs from a different working directory, or when the file got excluded by your .gitignore, or when your build step did not copy it into the production bundle.

Same pattern: import config from '../../config/local.json'. The relative path resolves in development. In production, after the bundler did its thing, the path no longer exists.

The fix is to treat config as environment variables (the 12-factor way) and to load runtime data from a real data store, not from disk.

// Bad
const config = require('./config/local.json');

// Better
const config = {
  apiUrl: process.env.API_URL,
  dbUrl: process.env.DATABASE_URL,
  stripeKey: process.env.STRIPE_SECRET_KEY,
};

// Validate at boot so you fail loudly, not silently
const required = ['API_URL', 'DATABASE_URL', 'STRIPE_SECRET_KEY'];
const missing = required.filter(k => !process.env[k]);
if (missing.length) {
  console.error('Missing env vars:', missing.join(', '));
  process.exit(1);
}

Enter fullscreen mode Exit fullscreen mode

That process.exit(1) is doing a lot of work. It is the difference between "the app crashes loudly at boot with a clear error" and "the app appears to boot fine but then 500s on the first request that needs Stripe."

Pattern 6: The background work that never runs

Sending an email after signup. Charging a customer's card on the 1st of each month. Cleaning up expired sessions. The model wrote these as inline calls inside your HTTP handler, or as setTimeout calls that get dropped when the process restarts.

The first time you redeploy, the queued work disappears. The first time your server cold-starts, the in-memory timers vanish. The first time an email fails to send (because Mailgun returned a 429), your signup handler returns 500 and the user thinks the app is broken.

You need three things: a real background process (a worker), a real schedule (cron, not setTimeout), and retry logic with a dead-letter behavior.

Lightweight options that have worked for me on small teams: BullMQ on top of Redis, RQ for Python, Sidekiq for Rails, GoCron for Go. Or use your platform's managed worker tier if it has one.

The pattern in code:

// In the HTTP handler, do NOT send the email inline
await db.users.create({ email, hashedPassword });
await emailQueue.add('send-welcome', { userId: newUser.id });
return res.json({ ok: true });

// In the worker process
emailQueue.process('send-welcome', async (job) => {
  const user = await db.users.findById(job.data.userId);
  await mailer.send({
    to: user.email,
    template: 'welcome',
  });
  // BullMQ retries automatically with exponential backoff
});

Enter fullscreen mode Exit fullscreen mode

If something fails repeatedly, it goes to the dead-letter queue and you see it in a dashboard. The user's signup never broke. The email gets retried until it succeeds, or you decide it is hopeless.

What I built, because I kept solving these manually

After roughly the eighth time a non-tech founder messaged me at midnight with a vibe-coded app on fire, I built HostingGuru. It is a small European PaaS that runs your app from a GitHub repo, gives you a worker process if you need one, and watches your logs with a pattern-detection layer that catches the failure modes above (retry loops, hot Sentry fingerprints, latency spikes, silent cron failures) and pings me on Telegram. Free tier never sleeps, EU and US regions, encrypted env vars by default.

I am not telling you to use it. The patterns above work on Render, Railway, Fly, Vercel, AWS, or a Hetzner box you set up yourself. The point is: pick a platform that lets you have a worker process, real env vars, and log access. If your current setup does not, fix that before anything else.

What to do tonight, regardless of which platform you use

If you have a vibe-coded app in production right now, run this sweep. 30 minutes, maybe 45.

  1. grep -r "sk_live_\|api_key\|secret" dist/ .next/ public/ build/ against your built output. If anything matches, move the call to a backend route before you sleep.

  2. Open your three most-used database queries. Check for LIMIT. If it is missing, add it and a default of 50.

  3. Search your codebase for cors() with no arguments, or Access-Control-Allow-Origin: *. Replace with a whitelist of the 2 or 3 origins you actually need.

  4. Pick one date-handling code path (signup, billing, scheduled email). Verify it stores UTC and displays in user-local. If you cannot tell, log the Z suffix on the stored string and the Intl.DateTimeFormat output on the client.

  5. List your env vars. For each one, ask: would my app boot, or would it boot and then 500 on the first relevant request? Add a boot-time validator that crashes the process loudly if anything is missing.

  6. Find the one most important background job (welcome email, daily report, billing run). Verify it runs in a worker process or scheduled cron, not inside an HTTP handler.

  7. Set up one alert. Telegram, email, Slack, anything. The trigger does not need to be smart. "Error rate above 1% for 5 minutes" or "background job failed 3 times in a row" is enough to catch 80% of the bad nights.

The honest closing

Vibe-coded apps are not bad. They get founders shipping who otherwise could not ship, and that is wonderful. But the production gap is real, and every model I have used (Claude included) will confidently generate code that hides the six holes above. The model is doing what it was asked. You have to ask the next question.

I am curious: which of these six bit you the hardest? Or did you hit one I did not list? I have a strong suspicion there is a seventh I have not seen yet, and the comments here have been a good source of bug reports in the past.


Previous posts in this HostingGuru series:

  1. Heroku just went into "sustaining engineering mode." Here are 5 alternatives whose free tier actually doesn't sleep.
  2. I built my MVP with Claude Code. Now I need to deploy it. Here's what nobody tells you.
  3. Your AI app is silently burning $2,000/month and you don't know it. Here are the 5 patterns that bite founders.
  4. Telegram alerts for any production app, a 5-minute setup (no SaaS, no signup, just curl)
  5. How I built a Discord 'ship-tracker' bot in a weekend (and the 3-process architecture that keeps it alive 24/7)
  6. I migrated 12 client projects off Heroku. Here's the playbook (and the 7 things that bit me every single time).
  7. The Claude Code → production checklist: 15 things that aren't obvious until they bite you
  8. Your indie SaaS has zero working Postgres backups. Here's the 20-minute fix.
  9. Your Stripe webhook is going to silently drop a paid customer. Here are the 4 patterns that catch it before they chargeback.
  10. Your crontab is silently failing. The 5 silent killers of VPS-based cron jobs.