Blog — page 21 of 38
The Best GitHub Codespaces Alternatives in 2026
Cloud dev environments split into two jobs now: a place for humans to write code, and a place for agents to run it. Codespaces is good at the first and awkward at the second.
The Best Deno Deploy and Edge Function Alternatives in 2026
Edge runtimes are fast because they're constrained. When you hit the constraint — native modules, long jobs, a real database connection — you need a different shape of platform, not a different edge.
How to Deploy a Nuxt App Without Docker
Nuxt builds to a plain Node server. You don't need a container to run it — you need to get four things right: the output path, the port binding, runtime config, and which env vars exist at build time.
How to Run Cron Jobs Without Managing a Server
Getting a job to run at 2am is the easy part. Knowing it ran, making it safe to run twice, and finding out when it stops — that's the actual work.
How to Migrate from Heroku to MicroVM Hosting
Your Procfile becomes a start command, your config vars become env vars, your dynos become VMs. The app moves in an afternoon; the database is the part that needs a plan.
Build-time vs runtime environment variables
You set the environment variable. The dashboard shows it. The build still fails with 'undefined'. This is almost always the build-time versus runtime distinction, and frontend frameworks make it considerably more confusing than it needs to be.
Why your JavaScript build runs out of memory
It builds on your 32 GB laptop and dies on the build machine with an exit code 137 or a heap-out-of-memory stack trace. Here's what's actually consuming the memory and which fixes are real.
Schema migrations that don't take the site down
During a blue-green deploy, the old version and the new version are both talking to the same database. Every schema change has to be compatible with code that hasn't been deployed yet and code that's about to be deleted.
Running background workers next to your web app
Every app eventually needs work that outlives a request. Where that worker runs — same process, same machine, separate deployment — decides how it fails, and most teams pick by accident.
Hosting apps that hold persistent connections
A WebSocket connection is a long-lived, stateful thing on a platform designed around short, stateless requests. Every part of the deploy lifecycle has to be reconsidered, starting with what happens when you ship.
Deploying one service out of a monorepo
The repo has six apps and a dozen shared packages. You want to deploy one of them. Everything that makes a monorepo pleasant to develop in makes this step awkward, and the failures are all the same handful.
Deploying a Go service without writing a Dockerfile
Go produces one self-contained binary with no runtime to install. Wrapping that in a multi-stage Dockerfile to copy it into a scratch image is a lot of YAML to solve a problem Go already solved.
Connection pooling, and why you ran out of connections
Postgres gives every connection its own operating system process. That single design decision explains connection limits, why pooling exists, and why serverless functions are so good at exhausting a database.
Wiring an app to managed Postgres with Prisma or Drizzle
Creating the database is the easy part. Getting an ORM connected, migrations running in the right place, and TLS verified is where the afternoon goes — so here is the whole path, in order.
How much memory does your Postgres actually need?
The advice 'give Postgres as much RAM as your data' is expensive and usually wrong. What matters is the working set — and there's a query that tells you whether yours fits.
Backups you haven't restored aren't backups
Every team has backups. Far fewer can tell you how much data a failure would lose or how long a restore takes, and those two numbers are the only part of a backup strategy that matters.
The Postgres metrics worth watching
A default database dashboard shows CPU, memory and disk — three metrics that tell you almost nothing until it's too late. Here's what actually predicts a Postgres incident.
Testcontainers, and what comes after it
Testcontainers solved a genuine problem: tests against a real Postgres instead of a mock. The limits show up later, when the suite gets parallel and the CI runner is itself a container.
Getting realistic test data into ephemeral databases
Your fixtures have three users and five orders. Production has two million orders and a customer whose name contains an apostrophe. The bugs live in the gap between those, and closing it is a data problem.
Mocks that pass while production breaks
Every mock is a claim about how something behaves. The test suite verifies your code against the claim, not against reality — and the gap between those is where the interesting outages live.
Sharding a Playwright suite that has outgrown one machine
A Playwright suite grows until the feedback loop is too slow to use. Adding workers helps until the machine runs out of memory — after that you need shards, and shards need state that isn't shared.
Wiring preview environments into pull requests
Reading a diff tells you whether the code is reasonable. A URL tells you whether the feature works. Getting from one to the other is about a hundred lines of CI and one decision about databases.
Keeping a browser logged in without storing passwords
Most browser automation spends its first thirty seconds logging in, and most of its failures happen there too. There are three ways to skip it, and they differ in how much they keep.
Debugging a browser failure you can't reproduce
'Works on my machine' is a real technical statement about browser tests. The CI environment differs in about eight specific ways, and each one produces a recognisable failure.