<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: The Saint</title>
    <description>The latest articles on DEV Community by The Saint (@the_saint_dac63e343ee8704).</description>
    <link>https://dev.to/the_saint_dac63e343ee8704</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4012334%2F54ab9b77-3cfe-44cb-ba65-f72e5ac65d1e.png</url>
      <title>DEV Community: The Saint</title>
      <link>https://dev.to/the_saint_dac63e343ee8704</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/the_saint_dac63e343ee8704"/>
    <language>en</language>
    <item>
      <title>The Hardest Part of Building a Developer Tool Isn't Writing Code</title>
      <dc:creator>The Saint</dc:creator>
      <pubDate>Sun, 11 Oct 2026 08:59:21 +0000</pubDate>
      <link>https://dev.to/the_saint_dac63e343ee8704/the-hardest-part-of-building-a-developer-tool-isnt-writing-code-11oi</link>
      <guid>https://dev.to/the_saint_dac63e343ee8704/the-hardest-part-of-building-a-developer-tool-isnt-writing-code-11oi</guid>
      <description>&lt;p&gt;Building software is addictive.&lt;br&gt;
You think of a feature, open your editor, write some code, and eventually watch the idea become something real.&lt;br&gt;
That feeling is difficult to beat.&lt;br&gt;
But when you're building a product rather than working on an isolated project, there's a problem: you can spend months building things without getting any closer to building a product people actually need.&lt;br&gt;
I've been thinking about this while working on developer tools.&lt;br&gt;
The challenge isn't always figuring out how to implement something. Sometimes, it's deciding whether it should exist in the first place.&lt;br&gt;
The feature trap&lt;br&gt;
Imagine you're building a tool for developers.&lt;br&gt;
You start with a clear problem to solve. Then you notice another problem you could address.&lt;br&gt;
You add a feature.&lt;br&gt;
While implementing it, you discover something else that would make the experience better. You add that, too.&lt;br&gt;
Before long, your roadmap contains authentication, analytics, integrations, monitoring, deployment, automation, and several other ideas.&lt;br&gt;
Individually, each feature makes sense.&lt;br&gt;
Together, they can make the product harder to understand, harder to maintain, and harder to launch.&lt;br&gt;
The dangerous part is that you're still making progress.&lt;br&gt;
Your codebase is growing. Your feature list is getting longer. Your product looks more impressive.&lt;br&gt;
But none of those things necessarily means you've found product-market fit.&lt;br&gt;
You might simply be getting better at building things that people haven't asked for.&lt;br&gt;
More features don't automatically create more value&lt;br&gt;
A feature has at least two costs.&lt;br&gt;
The first is the cost of building it.&lt;br&gt;
The second is the cost of keeping it working.&lt;br&gt;
Every new capability can introduce additional edge cases, bugs, documentation requirements, support requests, and maintenance work.&lt;br&gt;
Integrations need to be maintained. APIs change. Dependencies become outdated. User expectations grow.&lt;br&gt;
A feature that takes two days to implement might create months of maintenance.&lt;br&gt;
This doesn't mean we should avoid ambitious products. It means we should understand the difference between the cost of creating a feature and the cost of owning it.&lt;br&gt;
For a small team, that distinction matters enormously.&lt;br&gt;
Start with the problem, not the feature&lt;br&gt;
When evaluating a new feature, I think these questions are more useful than asking whether it would be cool to build.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Who specifically has this problem?
If the answer is everyone, the answer probably isn't specific enough.
Identify the people who experience the problem and understand how they currently deal with it.&lt;/li&gt;
&lt;li&gt;How painful is the problem?
A minor inconvenience might not justify a new product feature.
A problem that repeatedly wastes hours, causes failures, or forces people to pay for several disconnected tools might be worth investigating.&lt;/li&gt;
&lt;li&gt;What do people do today?
Look at existing workflows, competitors, spreadsheets, scripts, workarounds, and manual processes.
The way people solve a problem today can reveal more than a list of features they say they want.&lt;/li&gt;
&lt;li&gt;Can we test the idea before fully building it?
Sometimes a prototype, landing page, manual service, or small experiment can tell you whether the idea deserves more investment.
You don't always need to build the entire system to test the underlying assumption.&lt;/li&gt;
&lt;li&gt;What will we stop doing to make room for it?
This is the question I think early-stage builders should ask more often.
Time is limited.
If a new feature takes two weeks, those are two weeks you cannot spend improving onboarding, fixing an existing problem, talking to users, or finding customers.
A roadmap should reflect those trade-offs.
Distribution is part of building the product
There's another trap developers can fall into: believing that a better product will automatically attract users.
It won't.
People need to discover your product, understand what it does, see why it matters, and decide that trying it is worth their time.
That means distribution cannot always wait until development is finished.
You can have excellent engineering and still struggle to get users if nobody knows your product exists.
For an early-stage startup, speaking to potential users, publishing useful content, participating in developer communities, and testing acquisition channels are not distractions from building.
They are part of discovering what is worth building.
What I'd do differently with a new product
If I were starting another developer tool from scratch, I'd keep the initial plan deliberately narrow.
I'd identify one specific audience and one painful problem.
Then I'd build the smallest version that could solve that problem for a real user.
I'd put it in front of people early, observe what they actually do, and use that information to decide what comes next.
I'd keep a separate list of interesting ideas so I wouldn't confuse an idea worth remembering with a feature worth implementing immediately.
Most importantly, I'd measure progress by what users can accomplish, not simply by how much code I've written.
The goal isn't to build the smallest product possible forever.
It's to earn the right to build a bigger product by proving that the smaller one is useful.
Final thought
Building software rewards people who can execute.
Building a sustainable product also requires knowing when not to execute.
There will always be another feature to add, another integration to support, and another idea that seems too good to ignore.
But an early-stage team doesn't have unlimited time or resources.
Sometimes, the most valuable thing you can do for your product is leave a good idea unbuilt.
I'm curious about other builders' experiences:
What's one feature you were convinced you needed, but later realised you could have shipped without?
I'd like to hear the reasoning behind it.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>startup</category>
      <category>productivity</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Your Application Is Not Your Server: Why Production Monitoring Needs Both</title>
      <dc:creator>The Saint</dc:creator>
      <pubDate>Fri, 09 Oct 2026 19:20:30 +0000</pubDate>
      <link>https://dev.to/the_saint_dac63e343ee8704/your-application-is-not-your-server-why-production-monitoring-needs-both-56m7</link>
      <guid>https://dev.to/the_saint_dac63e343ee8704/your-application-is-not-your-server-why-production-monitoring-needs-both-56m7</guid>
      <description>&lt;p&gt;Building an application and keeping it healthy in production are two different engineering problems.&lt;/p&gt;

&lt;p&gt;You can have an application that starts successfully, responds to requests, and looks perfectly fine during a quick manual test. Then, under real usage, requests become slow, errors appear, or the application stops responding entirely.&lt;/p&gt;

&lt;p&gt;When that happens, where do you look?&lt;/p&gt;

&lt;p&gt;The application? The server? The network? The disk?&lt;/p&gt;

&lt;p&gt;The answer depends on what failed. That's why production monitoring needs to look at both the application and the infrastructure underneath it.&lt;/p&gt;

&lt;p&gt;Application health is only half the picture&lt;/p&gt;

&lt;p&gt;Application monitoring focuses on what the software itself is doing.&lt;/p&gt;

&lt;p&gt;Depending on the monitoring setup, useful signals include:&lt;/p&gt;

&lt;p&gt;Runtime errors and crashes&lt;/p&gt;

&lt;p&gt;Application availability&lt;/p&gt;

&lt;p&gt;Downtime&lt;/p&gt;

&lt;p&gt;Failed requests and unexpected behavior&lt;/p&gt;

&lt;p&gt;These signals help answer questions such as:&lt;/p&gt;

&lt;p&gt;Is the application still running?&lt;/p&gt;

&lt;p&gt;Has the process crashed?&lt;/p&gt;

&lt;p&gt;Is the service available to users?&lt;/p&gt;

&lt;p&gt;Are runtime errors occurring?&lt;/p&gt;

&lt;p&gt;But an application can experience problems because of something outside its own code.&lt;/p&gt;

&lt;p&gt;For example, a database operation may start failing because the server is running out of disk space. Requests may become slow because CPU usage is consistently high. An otherwise healthy application may become unreachable because the underlying server is unavailable.&lt;/p&gt;

&lt;p&gt;Looking only at application-level signals can make those problems harder to investigate.&lt;/p&gt;

&lt;p&gt;The server has its own health indicators&lt;/p&gt;

&lt;p&gt;The infrastructure running an application produces useful signals of its own.&lt;/p&gt;

&lt;p&gt;CPU usage: Sustained high CPU utilization can indicate that a workload is overwhelming available compute capacity.&lt;/p&gt;

&lt;p&gt;Disk space: A nearly full disk can affect logs, temporary files, databases and other write operations.&lt;/p&gt;

&lt;p&gt;Network latency: Increasing latency can indicate a connectivity or performance problem somewhere along the relevant network path.&lt;/p&gt;

&lt;p&gt;Server availability: If the underlying server becomes unavailable, applications hosted on it can become unreachable regardless of whether their code was healthy before the incident.&lt;/p&gt;

&lt;p&gt;These metrics don't automatically identify the root cause of every incident. They do, however, give you more information to investigate the problem.&lt;/p&gt;

&lt;p&gt;The important point is that application health and server health are related, but they aren't the same thing.&lt;/p&gt;

&lt;p&gt;Why small teams need both&lt;/p&gt;

&lt;p&gt;Large engineering organizations can build elaborate observability stacks with separate tools for metrics, logs, traces, alert routing and infrastructure monitoring.&lt;/p&gt;

&lt;p&gt;Small teams and independent developers often have a different problem: too many tools to configure and too many places to check when something breaks.&lt;/p&gt;

&lt;p&gt;The goal shouldn't be to collect every possible metric. It should be to collect enough useful signals to notice problems and begin investigating them.&lt;/p&gt;

&lt;p&gt;A practical starting point is:&lt;/p&gt;

&lt;p&gt;Know when the application becomes unavailable.&lt;/p&gt;

&lt;p&gt;Detect important runtime failures.&lt;/p&gt;

&lt;p&gt;Watch resource pressure on the underlying server.&lt;/p&gt;

&lt;p&gt;Alert the people responsible when something needs attention.&lt;/p&gt;

&lt;p&gt;Have a clear path to investigate the issue.&lt;/p&gt;

&lt;p&gt;Alert delivery matters, too. A dashboard is useful when you're looking at it. An alert is useful when you're doing something else.&lt;/p&gt;

&lt;p&gt;Email, Slack and Telegram provide different ways to route notifications into workflows developers already use.&lt;/p&gt;

&lt;p&gt;Bringing application and server monitoring together&lt;/p&gt;

&lt;p&gt;This is the problem we're addressing with Monitor, the sixth pillar of CrescoDB.&lt;/p&gt;

&lt;p&gt;CrescoDB is expanding its lifecycle tooling across Build, Own, Verify, Deploy, Operate and Monitor.&lt;/p&gt;

&lt;p&gt;With Monitor, we're bringing visibility into both the application and its underlying server. That includes application crashes, runtime errors and downtime, alongside server signals such as CPU usage, disk space, network latency and server availability.&lt;/p&gt;

&lt;p&gt;When something goes wrong, alerts can be sent through email, Slack and Telegram.&lt;/p&gt;

&lt;p&gt;The goal isn't to claim that one dashboard eliminates every production incident. It's to give developers a clearer view of what's happening across the layers they depend on.&lt;/p&gt;

&lt;p&gt;Monitoring belongs in the deployment workflow&lt;/p&gt;

&lt;p&gt;Deployment is not the end of the software lifecycle.&lt;/p&gt;

&lt;p&gt;After deployment, an application needs to keep running, respond to users, use resources responsibly and remain available as conditions change.&lt;/p&gt;

&lt;p&gt;That is why we think about the lifecycle as:&lt;/p&gt;

&lt;p&gt;Build → Own → Verify → Deploy → Operate → Monitor&lt;/p&gt;

&lt;p&gt;Each stage addresses a different concern, but they work together. Verification helps catch problems before release. Deployment gets the application running. Operations keep it running. Monitoring helps reveal when something needs attention.&lt;/p&gt;

&lt;p&gt;We're building CrescoDB around that connected workflow because developers shouldn't have to treat production reliability as an afterthought.&lt;/p&gt;

&lt;p&gt;A question for developers&lt;/p&gt;

&lt;p&gt;When one of your applications starts failing, how quickly can you tell whether the problem is in the application or the infrastructure running it?&lt;/p&gt;

&lt;p&gt;And what do you use to monitor both?&lt;/p&gt;

&lt;p&gt;We're building CrescoDB to make that workflow simpler. You can explore it at &lt;a href="https://crescodb.com" rel="noopener noreferrer"&gt;https://crescodb.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>devops</category>
    </item>
    <item>
      <title>Your App Being “Online” Doesn’t Mean It’s Healthy</title>
      <dc:creator>The Saint</dc:creator>
      <pubDate>Tue, 06 Oct 2026 07:21:21 +0000</pubDate>
      <link>https://dev.to/the_saint_dac63e343ee8704/your-app-being-online-doesnt-mean-its-healthy-538c</link>
      <guid>https://dev.to/the_saint_dac63e343ee8704/your-app-being-online-doesnt-mean-its-healthy-538c</guid>
      <description>&lt;p&gt;One of the easiest traps in production is assuming:&lt;/p&gt;

&lt;p&gt;“The website is responding, so everything is fine.”&lt;/p&gt;

&lt;p&gt;It isn't.&lt;/p&gt;

&lt;p&gt;An application can technically be online while quietly falling apart underneath.&lt;/p&gt;

&lt;p&gt;Your API might still respond while CPU usage sits at 95%.&lt;/p&gt;

&lt;p&gt;Your server might still accept traffic while disk space has 300 MB left.&lt;/p&gt;

&lt;p&gt;Your database might be reachable while requests are taking five seconds instead of 200 milliseconds.&lt;/p&gt;

&lt;p&gt;Your process might still be running while one important background worker died twenty minutes ago.&lt;/p&gt;

&lt;p&gt;And sometimes the first person to tell you something is wrong is a user.&lt;/p&gt;

&lt;p&gt;That's usually too late.&lt;/p&gt;

&lt;p&gt;Uptime is only one signal&lt;/p&gt;

&lt;p&gt;The simplest form of monitoring asks one question:&lt;/p&gt;

&lt;p&gt;Is the application reachable?&lt;/p&gt;

&lt;p&gt;You send a request every few seconds or minutes.&lt;/p&gt;

&lt;p&gt;If it returns successfully:&lt;/p&gt;

&lt;p&gt;everything looks green.&lt;/p&gt;

&lt;p&gt;If it stops responding:&lt;/p&gt;

&lt;p&gt;send an alert.&lt;/p&gt;

&lt;p&gt;That is useful.&lt;/p&gt;

&lt;p&gt;But it only detects one class of failure.&lt;/p&gt;

&lt;p&gt;Production systems often degrade long before they completely disappear.&lt;/p&gt;

&lt;p&gt;Imagine this:&lt;/p&gt;

&lt;p&gt;Technically, the server is alive.&lt;/p&gt;

&lt;p&gt;Operationally, you should probably be worried.&lt;/p&gt;

&lt;p&gt;Monitoring the application&lt;/p&gt;

&lt;p&gt;Application monitoring looks at what is happening inside the software.&lt;/p&gt;

&lt;p&gt;Things like:&lt;/p&gt;

&lt;p&gt;application crashes&lt;br&gt;
unhandled exceptions&lt;br&gt;
failed requests&lt;br&gt;
response time&lt;br&gt;
API errors&lt;br&gt;
runtime failures&lt;br&gt;
unhealthy processes&lt;br&gt;
failed jobs&lt;/p&gt;

&lt;p&gt;Consider an API that normally responds in:&lt;/p&gt;

&lt;p&gt;and gradually moves to:&lt;/p&gt;

&lt;p&gt;Nothing has technically crashed.&lt;/p&gt;

&lt;p&gt;But something has changed.&lt;/p&gt;

&lt;p&gt;Maybe a database query became slower.&lt;/p&gt;

&lt;p&gt;Maybe traffic increased.&lt;/p&gt;

&lt;p&gt;Maybe a dependency is struggling.&lt;/p&gt;

&lt;p&gt;Maybe memory pressure is causing garbage collection problems.&lt;/p&gt;

&lt;p&gt;Monitoring gives you a chance to investigate before the application becomes unavailable.&lt;/p&gt;

&lt;p&gt;Then there is the machine underneath it&lt;/p&gt;

&lt;p&gt;This is the part I think developers sometimes forget.&lt;/p&gt;

&lt;p&gt;Your application isn't floating in the cloud.&lt;/p&gt;

&lt;p&gt;Eventually, it is running on a machine somewhere.&lt;/p&gt;

&lt;p&gt;That machine has:&lt;/p&gt;

&lt;p&gt;And any one of those can become the actual reason your application fails.&lt;/p&gt;

&lt;p&gt;For example, your Node.js API might be perfectly written.&lt;/p&gt;

&lt;p&gt;but It doesn't matter if the VPS disk is full.&lt;/p&gt;

&lt;p&gt;Your application can't write new files.&lt;/p&gt;

&lt;p&gt;Your database may not be able to expand.&lt;/p&gt;

&lt;p&gt;Logs stop being written.&lt;/p&gt;

&lt;p&gt;Eventually, things start breaking in strange ways.&lt;/p&gt;

&lt;p&gt;The application is the symptom.&lt;/p&gt;

&lt;p&gt;The server is the cause.&lt;/p&gt;

&lt;p&gt;CPU spikes matter&lt;/p&gt;

&lt;p&gt;Suppose your server normally runs around:&lt;/p&gt;

&lt;p&gt;Then suddenly:&lt;/p&gt;

&lt;p&gt;for several minutes.&lt;/p&gt;

&lt;p&gt;That might mean:&lt;/p&gt;

&lt;p&gt;unexpected traffic&lt;br&gt;
runaway process&lt;br&gt;
expensive database operation&lt;br&gt;
infinite loop&lt;br&gt;
background job&lt;br&gt;
compromised server&lt;br&gt;
badly optimized code&lt;/p&gt;

&lt;p&gt;You don't necessarily want an alert every time CPU touches 90% for three seconds.&lt;/p&gt;

&lt;p&gt;That would become noise.&lt;/p&gt;

&lt;p&gt;But sustained abnormal usage?&lt;/p&gt;

&lt;p&gt;You probably want to know.&lt;/p&gt;

&lt;p&gt;Something like:&lt;/p&gt;

&lt;p&gt;CPU usage has remained above 90% for 5 minutes.&lt;/p&gt;

&lt;p&gt;That's actionable.&lt;/p&gt;

&lt;p&gt;Disk space is boring until it destroys your weekend&lt;/p&gt;

&lt;p&gt;Disk monitoring might be one of the least exciting things in software.&lt;/p&gt;

&lt;p&gt;Until this happens:&lt;/p&gt;

&lt;p&gt;Databases need disk.&lt;/p&gt;

&lt;p&gt;Logs need disk.&lt;/p&gt;

&lt;p&gt;Uploads need disk.&lt;/p&gt;

&lt;p&gt;Temporary files need disk.&lt;/p&gt;

&lt;p&gt;Docker images need disk.&lt;/p&gt;

&lt;p&gt;Backups may need disk.&lt;/p&gt;

&lt;p&gt;A slowly growing log directory can quietly consume storage for weeks before anything obviously fails.&lt;/p&gt;

&lt;p&gt;So instead of discovering:&lt;/p&gt;

&lt;p&gt;after the damage starts, monitoring should warn you earlier:&lt;/p&gt;

&lt;p&gt;The alert isn't the solution.&lt;/p&gt;

&lt;p&gt;It gives you time to create one.&lt;/p&gt;

&lt;p&gt;Network problems are different from downtime&lt;/p&gt;

&lt;p&gt;A server can be reachable and still have terrible connectivity.&lt;/p&gt;

&lt;p&gt;Maybe:&lt;/p&gt;

&lt;p&gt;Your users experience the application as slow.&lt;/p&gt;

&lt;p&gt;Your uptime monitor says:&lt;/p&gt;

&lt;p&gt;All systems operational.&lt;/p&gt;

&lt;p&gt;Both statements can technically be true.&lt;/p&gt;

&lt;p&gt;This is why latency belongs beside uptime.&lt;/p&gt;

&lt;p&gt;You want to understand:&lt;/p&gt;

&lt;p&gt;Is the server reachable?&lt;br&gt;
How quickly is it responding?&lt;br&gt;
Has network latency changed?&lt;br&gt;
Are packets being dropped?&lt;br&gt;
Is one region behaving differently?&lt;/p&gt;

&lt;p&gt;Availability and performance are related, but they are not the same thing.&lt;/p&gt;

&lt;p&gt;Monitoring without alerts is just a dashboard&lt;/p&gt;

&lt;p&gt;There is another mistake I've seen:&lt;/p&gt;

&lt;p&gt;Beautiful monitoring dashboards.&lt;/p&gt;

&lt;p&gt;Charts everywhere.&lt;/p&gt;

&lt;p&gt;CPU graphs.&lt;/p&gt;

&lt;p&gt;Memory graphs.&lt;/p&gt;

&lt;p&gt;Latency graphs.&lt;/p&gt;

&lt;p&gt;Error graphs.&lt;/p&gt;

&lt;p&gt;But nobody is staring at those dashboards at 3:17 AM.&lt;/p&gt;

&lt;p&gt;A monitoring system needs a way to say:&lt;/p&gt;

&lt;p&gt;Something changed. You should look at this.&lt;/p&gt;

&lt;p&gt;That could be:&lt;/p&gt;

&lt;p&gt;depending on how the team works.&lt;/p&gt;

&lt;p&gt;The important part is delivering the right alert to somebody capable of acting on it.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;Production API Down&lt;/p&gt;

&lt;p&gt;api.example.com has failed 3 consecutive health checks.&lt;/p&gt;

&lt;p&gt;Last successful check: 02:41 UTC&lt;/p&gt;

&lt;p&gt;Or:&lt;/p&gt;

&lt;p&gt;Server CPU Alert&lt;/p&gt;

&lt;p&gt;CPU usage on production-01 has remained above 90% for 5 minutes.&lt;/p&gt;

&lt;p&gt;That is much more useful than discovering the problem because somebody posted:&lt;/p&gt;

&lt;p&gt;“Is your site down?”&lt;/p&gt;

&lt;p&gt;on Twitter.&lt;/p&gt;

&lt;p&gt;But alerts can also become useless&lt;/p&gt;

&lt;p&gt;The opposite problem is alert fatigue.&lt;/p&gt;

&lt;p&gt;If your system tells you:&lt;/p&gt;

&lt;p&gt;every thirty seconds, you eventually stop caring.&lt;/p&gt;

&lt;p&gt;Then the important notification gets buried with everything else.&lt;/p&gt;

&lt;p&gt;Good monitoring needs thresholds.&lt;/p&gt;

&lt;p&gt;And often, duration.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;p&gt;CPU crossed 80%.&lt;/p&gt;

&lt;p&gt;think:&lt;/p&gt;

&lt;p&gt;CPU remained above 85% for five minutes.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;p&gt;One request failed.&lt;/p&gt;

&lt;p&gt;think:&lt;/p&gt;

&lt;p&gt;Error rate exceeded 5% over the last five minutes.&lt;/p&gt;

&lt;p&gt;The goal isn't maximum notifications.&lt;/p&gt;

&lt;p&gt;The goal is useful awareness.&lt;/p&gt;

&lt;p&gt;Monitoring should exist at multiple layers&lt;/p&gt;

&lt;p&gt;I've started thinking about production monitoring as two connected systems.&lt;/p&gt;

&lt;p&gt;Layer 1 — Application&lt;/p&gt;

&lt;p&gt;Watch:&lt;/p&gt;

&lt;p&gt;Layer 2 — Infrastructure&lt;/p&gt;

&lt;p&gt;Watch:&lt;/p&gt;

&lt;p&gt;Because sometimes the application is broken.&lt;/p&gt;

&lt;p&gt;Sometimes the infrastructure is broken.&lt;/p&gt;

&lt;p&gt;And sometimes one is telling you something about the other.&lt;/p&gt;

&lt;p&gt;Seeing both makes diagnosis much easier.&lt;/p&gt;

&lt;p&gt;Monitoring shouldn't begin after something breaks&lt;/p&gt;

&lt;p&gt;This is probably the most important part.&lt;/p&gt;

&lt;p&gt;Teams often add monitoring after their first serious incident.&lt;/p&gt;

&lt;p&gt;Something goes down.&lt;/p&gt;

&lt;p&gt;Nobody notices for forty minutes.&lt;/p&gt;

&lt;p&gt;Users complain.&lt;/p&gt;

&lt;p&gt;The team fixes it.&lt;/p&gt;

&lt;p&gt;Then someone says:&lt;/p&gt;

&lt;p&gt;“We should probably add monitoring.”&lt;/p&gt;

&lt;p&gt;Monitoring shouldn't be the postmortem action item.&lt;/p&gt;

&lt;p&gt;It should be part of getting something into production.&lt;/p&gt;

&lt;p&gt;I've increasingly started thinking about the backend lifecycle as:&lt;/p&gt;

&lt;p&gt;Build → Verify → Deploy → Operate → Own → Monitor&lt;/p&gt;

&lt;p&gt;Building answers:&lt;/p&gt;

&lt;p&gt;Can we create it?&lt;/p&gt;

&lt;p&gt;Verification asks:&lt;/p&gt;

&lt;p&gt;Does it behave correctly?&lt;/p&gt;

&lt;p&gt;Deployment asks:&lt;/p&gt;

&lt;p&gt;Can we get it into production?&lt;/p&gt;

&lt;p&gt;Operations asks:&lt;/p&gt;

&lt;p&gt;Can we manage it there?&lt;/p&gt;

&lt;p&gt;Ownership asks:&lt;/p&gt;

&lt;p&gt;Do we retain control of what we're running?&lt;/p&gt;

&lt;p&gt;And monitoring asks:&lt;/p&gt;

&lt;p&gt;Will we know when something changes?&lt;/p&gt;

&lt;p&gt;That last question matters more once nobody is sitting there watching the terminal.&lt;/p&gt;

&lt;p&gt;This is something we're working on ourselves&lt;/p&gt;

&lt;p&gt;We've been thinking about this while building CrescoDB.&lt;/p&gt;

&lt;p&gt;CrescoDB already manages the production server layer for projects deployed through it, so we can see things like server availability and runtime health.&lt;/p&gt;

&lt;p&gt;We're now expanding that into a more complete monitoring layer.&lt;/p&gt;

&lt;p&gt;Not an attempt to recreate every observability feature from platforms built entirely around monitoring.&lt;/p&gt;

&lt;p&gt;The goal is simpler:&lt;/p&gt;

&lt;p&gt;Give smaller engineering teams the information they actually need to know when something is going wrong.&lt;/p&gt;

&lt;p&gt;At the application level:&lt;/p&gt;

&lt;p&gt;And underneath that:&lt;/p&gt;

&lt;p&gt;Then push useful alerts through the channels teams are already watching:&lt;/p&gt;

&lt;p&gt;Telegram, Slack and email.&lt;/p&gt;

&lt;p&gt;The interesting part for us isn't adding another dashboard.&lt;/p&gt;

&lt;p&gt;It's connecting application health with the infrastructure running it.&lt;/p&gt;

&lt;p&gt;Because if your API goes down at the same moment the server's memory hits 98%, those two pieces of information probably belong beside each other.&lt;/p&gt;

&lt;p&gt;Production is really about feedback&lt;/p&gt;

&lt;p&gt;When you're developing locally, feedback is immediate.&lt;/p&gt;

&lt;p&gt;Something breaks.&lt;/p&gt;

&lt;p&gt;Your terminal tells you.&lt;/p&gt;

&lt;p&gt;You fix it.&lt;/p&gt;

&lt;p&gt;Production creates distance between the developer and the software.&lt;/p&gt;

&lt;p&gt;Monitoring closes some of that distance.&lt;/p&gt;

&lt;p&gt;It tells you:&lt;/p&gt;

&lt;p&gt;Something changed.&lt;/p&gt;

&lt;p&gt;before the user has to.&lt;/p&gt;

&lt;p&gt;And that might be the simplest definition of good monitoring:&lt;/p&gt;

&lt;p&gt;Knowing your software is unhealthy before your customers do.&lt;/p&gt;

&lt;p&gt;What production issue have you had that proper monitoring would have caught earlier?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>devops</category>
      <category>backend</category>
    </item>
    <item>
      <title>AI Made Building Software Faster. It Didn’t Make Production Easier</title>
      <dc:creator>The Saint</dc:creator>
      <pubDate>Fri, 02 Oct 2026 09:00:12 +0000</pubDate>
      <link>https://dev.to/the_saint_dac63e343ee8704/ai-made-building-software-faster-it-didnt-make-production-easier-1igi</link>
      <guid>https://dev.to/the_saint_dac63e343ee8704/ai-made-building-software-faster-it-didnt-make-production-easier-1igi</guid>
      <description>&lt;p&gt;A weird thing is happening in software development.&lt;/p&gt;

&lt;p&gt;Building software has become ridiculously fast.&lt;/p&gt;

&lt;p&gt;You can describe an application to an AI coding tool and have a working interface within minutes.&lt;/p&gt;

&lt;p&gt;Need an API?&lt;/p&gt;

&lt;p&gt;Generated.&lt;/p&gt;

&lt;p&gt;Database schema?&lt;/p&gt;

&lt;p&gt;Generated.&lt;/p&gt;

&lt;p&gt;Authentication flow?&lt;/p&gt;

&lt;p&gt;Probably generated too.&lt;/p&gt;

&lt;p&gt;A solo developer can now build something in a weekend that might have taken a small team several weeks a few years ago.&lt;/p&gt;

&lt;p&gt;That is genuinely impressive.&lt;/p&gt;

&lt;p&gt;But there’s a point where the speed suddenly disappears.&lt;/p&gt;

&lt;p&gt;It usually happens around the moment someone says:&lt;/p&gt;

&lt;p&gt;“Alright. Put it in production.”&lt;/p&gt;

&lt;p&gt;And now you have a completely different problem.&lt;/p&gt;

&lt;p&gt;Generating code and running software are different jobs&lt;/p&gt;

&lt;p&gt;AI is extremely good at helping us produce software.&lt;/p&gt;

&lt;p&gt;It can generate:&lt;/p&gt;

&lt;p&gt;routes&lt;br&gt;
database models&lt;br&gt;
API handlers&lt;br&gt;
authentication&lt;br&gt;
tests&lt;br&gt;
Dockerfiles&lt;br&gt;
CI configs&lt;/p&gt;

&lt;p&gt;But generating those things doesn't automatically mean the resulting system is ready to serve real users.&lt;/p&gt;

&lt;p&gt;Production introduces questions that don't matter nearly as much while you're working locally.&lt;/p&gt;

&lt;p&gt;What happens if your server crashes?&lt;/p&gt;

&lt;p&gt;What happens if a database migration fails halfway through?&lt;/p&gt;

&lt;p&gt;What happens when two users modify the same data simultaneously?&lt;/p&gt;

&lt;p&gt;Where are your logs?&lt;/p&gt;

&lt;p&gt;How do you know the application is healthy?&lt;/p&gt;

&lt;p&gt;Where are your backups?&lt;/p&gt;

&lt;p&gt;Have you ever restored one?&lt;/p&gt;

&lt;p&gt;How do you roll back a bad deployment?&lt;/p&gt;

&lt;p&gt;What happens when your server runs out of memory?&lt;/p&gt;

&lt;p&gt;Who gets alerted when any of this happens?&lt;/p&gt;

&lt;p&gt;AI can help answer every one of those questions.&lt;/p&gt;

&lt;p&gt;But somebody still has to ask them.&lt;/p&gt;

&lt;p&gt;The bottleneck is moving&lt;/p&gt;

&lt;p&gt;For years, one of the biggest constraints in software was simply writing the thing.&lt;/p&gt;

&lt;p&gt;You needed enough engineering hours to turn an idea into functioning software.&lt;/p&gt;

&lt;p&gt;AI is reducing that constraint.&lt;/p&gt;

&lt;p&gt;Not eliminating it, but reducing it significantly.&lt;/p&gt;

&lt;p&gt;So another constraint becomes more visible:&lt;/p&gt;

&lt;p&gt;Operating what we build.&lt;/p&gt;

&lt;p&gt;We are creating applications faster than ever.&lt;/p&gt;

&lt;p&gt;But those applications still need databases, deployments, infrastructure, monitoring, migrations, security, backups and recovery.&lt;/p&gt;

&lt;p&gt;If development becomes 5x faster while everything after development remains roughly the same, then production becomes a larger percentage of the work.&lt;/p&gt;

&lt;p&gt;That changes the developer workflow.&lt;/p&gt;

&lt;p&gt;“It works” is becoming an increasingly dangerous milestone&lt;/p&gt;

&lt;p&gt;There's a huge difference between:&lt;/p&gt;

&lt;p&gt;It works.&lt;/p&gt;

&lt;p&gt;and:&lt;/p&gt;

&lt;p&gt;It can survive production.&lt;/p&gt;

&lt;p&gt;An application running on your laptop usually has ideal conditions.&lt;/p&gt;

&lt;p&gt;You're probably the only user.&lt;/p&gt;

&lt;p&gt;The database is nearby.&lt;/p&gt;

&lt;p&gt;You know the environment.&lt;/p&gt;

&lt;p&gt;You can restart everything.&lt;/p&gt;

&lt;p&gt;You can read the terminal directly.&lt;/p&gt;

&lt;p&gt;If something breaks, you are literally sitting in front of it.&lt;/p&gt;

&lt;p&gt;Production removes most of those advantages.&lt;/p&gt;

&lt;p&gt;Now the application needs to behave correctly when nobody is watching.&lt;/p&gt;

&lt;p&gt;That means the definition of “finished” starts expanding.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;p&gt;Feature works ✓&lt;/p&gt;

&lt;p&gt;you eventually need something closer to:&lt;/p&gt;

&lt;p&gt;Feature works ✓&lt;/p&gt;

&lt;p&gt;Tests pass ✓&lt;/p&gt;

&lt;p&gt;Configuration verified ✓&lt;/p&gt;

&lt;p&gt;Migration safe ✓&lt;/p&gt;

&lt;p&gt;Deployment reproducible ✓&lt;/p&gt;

&lt;p&gt;Monitoring active ✓&lt;/p&gt;

&lt;p&gt;Backups available ✓&lt;/p&gt;

&lt;p&gt;Rollback possible ✓&lt;/p&gt;

&lt;p&gt;This part is much less exciting than generating a beautiful application from a prompt.&lt;/p&gt;

&lt;p&gt;Unfortunately, users don't care which part was exciting.&lt;/p&gt;

&lt;p&gt;They care that the software works.&lt;/p&gt;

&lt;p&gt;AI can also create operational debt faster&lt;/p&gt;

&lt;p&gt;There's another side to faster development.&lt;/p&gt;

&lt;p&gt;When building becomes easier, it becomes easier to build more.&lt;/p&gt;

&lt;p&gt;More features.&lt;/p&gt;

&lt;p&gt;More endpoints.&lt;/p&gt;

&lt;p&gt;More dependencies.&lt;/p&gt;

&lt;p&gt;More services.&lt;/p&gt;

&lt;p&gt;More database tables.&lt;/p&gt;

&lt;p&gt;More infrastructure.&lt;/p&gt;

&lt;p&gt;And every additional moving part becomes something that might eventually need to be operated.&lt;/p&gt;

&lt;p&gt;You can create complexity faster than you can understand it.&lt;/p&gt;

&lt;p&gt;That's an interesting problem.&lt;/p&gt;

&lt;p&gt;A developer might previously spend three days implementing a feature and naturally become familiar with almost every part of it.&lt;/p&gt;

&lt;p&gt;Now an AI agent might generate the same feature in twenty minutes.&lt;/p&gt;

&lt;p&gt;The output arrived faster.&lt;/p&gt;

&lt;p&gt;The developer's mental model did not necessarily accelerate at the same rate.&lt;/p&gt;

&lt;p&gt;That gap matters when something breaks.&lt;/p&gt;

&lt;p&gt;This changes what developers need to get good at&lt;/p&gt;

&lt;p&gt;I don't think the lesson is that developers should stop using AI.&lt;/p&gt;

&lt;p&gt;Quite the opposite.&lt;/p&gt;

&lt;p&gt;The productivity increase is too useful to ignore.&lt;/p&gt;

&lt;p&gt;But our skills probably need to move upward.&lt;/p&gt;

&lt;p&gt;Knowing how to generate code becomes less valuable than knowing how to evaluate it.&lt;/p&gt;

&lt;p&gt;Questions like:&lt;/p&gt;

&lt;p&gt;Is this architecture appropriate?&lt;br&gt;
What assumptions does this code make?&lt;br&gt;
What happens when this fails?&lt;br&gt;
Is this secure?&lt;br&gt;
How will I observe this in production?&lt;br&gt;
How do I recover from failure?&lt;br&gt;
What happens at 100x the current traffic?&lt;br&gt;
What dependencies am I introducing?&lt;/p&gt;

&lt;p&gt;Those questions become increasingly important.&lt;/p&gt;

&lt;p&gt;The job starts moving from:&lt;/p&gt;

&lt;p&gt;How do I write this?&lt;/p&gt;

&lt;p&gt;toward:&lt;/p&gt;

&lt;p&gt;How do I know this is actually good?&lt;/p&gt;

&lt;p&gt;That is a much more interesting engineering problem.&lt;/p&gt;

&lt;p&gt;Production is where abstractions meet reality&lt;/p&gt;

&lt;p&gt;Development tools can hide an enormous amount of complexity.&lt;/p&gt;

&lt;p&gt;And that's usually a good thing.&lt;/p&gt;

&lt;p&gt;Good abstractions let us build faster.&lt;/p&gt;

&lt;p&gt;But production eventually exposes whatever the abstraction didn't cover.&lt;/p&gt;

&lt;p&gt;Your database doesn't care how quickly the application was generated when a migration locks a table.&lt;/p&gt;

&lt;p&gt;Your server doesn't care that an AI wrote the endpoint when memory usage keeps growing.&lt;/p&gt;

&lt;p&gt;Your users don't care how impressive the development process was when authentication goes down.&lt;/p&gt;

&lt;p&gt;Reality remains annoyingly traditional.&lt;/p&gt;

&lt;p&gt;Networks fail.&lt;/p&gt;

&lt;p&gt;Disks fill.&lt;/p&gt;

&lt;p&gt;Processes crash.&lt;/p&gt;

&lt;p&gt;Humans make mistakes.&lt;/p&gt;

&lt;p&gt;Dependencies break.&lt;/p&gt;

&lt;p&gt;Credentials expire.&lt;/p&gt;

&lt;p&gt;And software has to deal with all of it.&lt;/p&gt;

&lt;p&gt;The next generation of developer tooling will probably move downstream&lt;/p&gt;

&lt;p&gt;We've spent the last few years making creation dramatically easier.&lt;/p&gt;

&lt;p&gt;AI coding agents.&lt;/p&gt;

&lt;p&gt;App generators.&lt;/p&gt;

&lt;p&gt;Better frameworks.&lt;/p&gt;

&lt;p&gt;Managed databases.&lt;/p&gt;

&lt;p&gt;Backend-as-a-service platforms.&lt;/p&gt;

&lt;p&gt;Component libraries.&lt;/p&gt;

&lt;p&gt;All of these reduce the time between idea and working software.&lt;/p&gt;

&lt;p&gt;The next major opportunity may be making everything after creation equally simple.&lt;/p&gt;

&lt;p&gt;Not just:&lt;/p&gt;

&lt;p&gt;Build&lt;/p&gt;

&lt;p&gt;but:&lt;/p&gt;

&lt;p&gt;Verify → Deploy → Operate → Recover&lt;/p&gt;

&lt;p&gt;Because if AI keeps making software creation faster, developers are going to produce more software.&lt;/p&gt;

&lt;p&gt;And all of that software eventually has to run somewhere.&lt;/p&gt;

&lt;p&gt;The interesting question isn't “Can AI build this?”&lt;/p&gt;

&lt;p&gt;We're rapidly reaching a point where the answer to that question is often:&lt;/p&gt;

&lt;p&gt;Probably.&lt;/p&gt;

&lt;p&gt;The more useful questions are becoming:&lt;/p&gt;

&lt;p&gt;Should we build it this way?&lt;/p&gt;

&lt;p&gt;Is it ready for production?&lt;/p&gt;

&lt;p&gt;Can we understand what happens when it fails?&lt;/p&gt;

&lt;p&gt;Can we safely operate it?&lt;/p&gt;

&lt;p&gt;Can we recover?&lt;/p&gt;

&lt;p&gt;The impressive part of software development is becoming easier.&lt;/p&gt;

&lt;p&gt;The boring part is becoming the bottleneck.&lt;/p&gt;

&lt;p&gt;And ironically, the boring part is usually what determines whether the software actually survives.&lt;/p&gt;

&lt;p&gt;Has AI made you ship faster, or has it just moved the difficult part of your work somewhere else?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>devops</category>
    </item>
    <item>
      <title>Writing About Code Has Made Me Better at Writing Code</title>
      <dc:creator>The Saint</dc:creator>
      <pubDate>Wed, 30 Sep 2026 08:07:50 +0000</pubDate>
      <link>https://dev.to/the_saint_dac63e343ee8704/writing-about-code-has-made-me-better-at-writing-code-3843</link>
      <guid>https://dev.to/the_saint_dac63e343ee8704/writing-about-code-has-made-me-better-at-writing-code-3843</guid>
      <description>&lt;p&gt;Most developers treat technical writing as something you do after you know what you're talking about.&lt;/p&gt;

&lt;p&gt;I've started thinking about it the other way around.&lt;/p&gt;

&lt;p&gt;Sometimes I don't realize how poorly I understand something until I try to explain it.&lt;/p&gt;

&lt;p&gt;You can spend hours working with a piece of technology and feel completely comfortable with it.&lt;/p&gt;

&lt;p&gt;Then somebody asks:&lt;/p&gt;

&lt;p&gt;Why does it work that way?&lt;/p&gt;

&lt;p&gt;And suddenly your brain goes:&lt;/p&gt;

&lt;p&gt;Well… it just does.&lt;/p&gt;

&lt;p&gt;That's usually the point where you discover the difference between recognizing something and actually understanding it.&lt;/p&gt;

&lt;p&gt;Code lets you hide behind working software&lt;/p&gt;

&lt;p&gt;Programming has an interesting loophole.&lt;/p&gt;

&lt;p&gt;Your code can work even when your mental model is incomplete.&lt;/p&gt;

&lt;p&gt;You can know that:&lt;/p&gt;

&lt;p&gt;await db.query(...)&lt;/p&gt;

&lt;p&gt;works.&lt;/p&gt;

&lt;p&gt;You can know where to put it.&lt;/p&gt;

&lt;p&gt;You can know how to handle the response.&lt;/p&gt;

&lt;p&gt;But that doesn't necessarily mean you understand:&lt;/p&gt;

&lt;p&gt;what happens when the connection drops&lt;br&gt;
how the connection pool behaves&lt;br&gt;
when the promise resolves&lt;br&gt;
what happens under concurrent requests&lt;br&gt;
how the database handles the query&lt;br&gt;
what failure actually looks like&lt;/p&gt;

&lt;p&gt;And that's fine.&lt;/p&gt;

&lt;p&gt;Nobody needs to understand every abstraction underneath every line of code they write.&lt;/p&gt;

&lt;p&gt;But the gaps become obvious when you attempt to explain the system to another person.&lt;/p&gt;

&lt;p&gt;Writing removes the autocomplete from your understanding.&lt;/p&gt;

&lt;p&gt;Explaining something forces you to find the missing pieces&lt;/p&gt;

&lt;p&gt;Let's say I want to write:&lt;/p&gt;

&lt;p&gt;"A database connection pool improves performance."&lt;/p&gt;

&lt;p&gt;Easy sentence.&lt;/p&gt;

&lt;p&gt;Then I ask myself:&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because we're reusing connections instead of creating one for every request.&lt;/p&gt;

&lt;p&gt;Okay.&lt;/p&gt;

&lt;p&gt;Why is opening a new database connection expensive?&lt;/p&gt;

&lt;p&gt;Now we're talking about networking, authentication, resource allocation and connection setup.&lt;/p&gt;

&lt;p&gt;What happens if the pool is exhausted?&lt;/p&gt;

&lt;p&gt;What decides how many connections should exist?&lt;/p&gt;

&lt;p&gt;Can too many connections make performance worse instead of better?&lt;/p&gt;

&lt;p&gt;Five minutes ago I thought I was writing one paragraph.&lt;/p&gt;

&lt;p&gt;Now I'm reading PostgreSQL documentation.&lt;/p&gt;

&lt;p&gt;That's what I like about writing.&lt;/p&gt;

&lt;p&gt;It exposes the edges of what you actually know.&lt;/p&gt;

&lt;p&gt;Tutorials are especially unforgiving&lt;/p&gt;

&lt;p&gt;When you're coding alone, you can skip steps mentally.&lt;/p&gt;

&lt;p&gt;You know that before this:&lt;/p&gt;

&lt;p&gt;npm run dev&lt;/p&gt;

&lt;p&gt;you already:&lt;/p&gt;

&lt;p&gt;npm install&lt;/p&gt;

&lt;p&gt;created .env, configured the database and probably fixed three errors you no longer remember.&lt;/p&gt;

&lt;p&gt;The reader doesn't know any of that.&lt;/p&gt;

&lt;p&gt;So when you're writing a tutorial, you have to reconstruct the real sequence.&lt;/p&gt;

&lt;p&gt;That forces you to think more carefully about:&lt;/p&gt;

&lt;p&gt;dependencies&lt;br&gt;
assumptions&lt;br&gt;
defaults&lt;br&gt;
edge cases&lt;br&gt;
setup&lt;br&gt;
failure states&lt;/p&gt;

&lt;p&gt;You begin noticing complexity you've learned to ignore.&lt;/p&gt;

&lt;p&gt;I've had several situations where writing about a workflow made me think:&lt;/p&gt;

&lt;p&gt;Why does this require so many steps in the first place?&lt;/p&gt;

&lt;p&gt;Which is also where product ideas tend to appear.&lt;/p&gt;

&lt;p&gt;Writing is surprisingly good product research&lt;/p&gt;

&lt;p&gt;This one wasn't obvious to me initially.&lt;/p&gt;

&lt;p&gt;When you try to explain a technical problem properly, you naturally start researching how other developers solve it.&lt;/p&gt;

&lt;p&gt;Suppose I'm writing about deploying a backend.&lt;/p&gt;

&lt;p&gt;I might start with:&lt;/p&gt;

&lt;p&gt;"Deploying a backend requires…"&lt;/p&gt;

&lt;p&gt;Then I need examples.&lt;/p&gt;

&lt;p&gt;So I start looking at:&lt;/p&gt;

&lt;p&gt;Docker&lt;br&gt;
Railway&lt;br&gt;
Render&lt;br&gt;
VPS deployments&lt;br&gt;
CI/CD&lt;br&gt;
migrations&lt;br&gt;
reverse proxies&lt;br&gt;
environment management&lt;br&gt;
health checks&lt;/p&gt;

&lt;p&gt;And while reading, patterns start showing up.&lt;/p&gt;

&lt;p&gt;Everyone has slightly different solutions to the same underlying problems.&lt;/p&gt;

&lt;p&gt;You start noticing where tools overlap.&lt;/p&gt;

&lt;p&gt;Where workflows are unnecessarily complicated.&lt;/p&gt;

&lt;p&gt;Where developers complain.&lt;/p&gt;

&lt;p&gt;Where documentation repeatedly has to explain the same thing.&lt;/p&gt;

&lt;p&gt;You weren't doing market research.&lt;/p&gt;

&lt;p&gt;You were trying to write a decent article.&lt;/p&gt;

&lt;p&gt;But you end up learning a lot about the market anyway.&lt;/p&gt;

&lt;p&gt;Writing also generates ideas&lt;/p&gt;

&lt;p&gt;One article tends to create five more.&lt;/p&gt;

&lt;p&gt;You start writing about logging.&lt;/p&gt;

&lt;p&gt;Then you realize error reporting deserves its own article.&lt;/p&gt;

&lt;p&gt;That leads to observability.&lt;/p&gt;

&lt;p&gt;Then production debugging.&lt;/p&gt;

&lt;p&gt;Then distributed tracing.&lt;/p&gt;

&lt;p&gt;Then suddenly you have a backlog of topics you didn't have yesterday.&lt;/p&gt;

&lt;p&gt;It's basically recursion for ideas.&lt;/p&gt;

&lt;p&gt;The most useful part is that the ideas aren't coming from:&lt;/p&gt;

&lt;p&gt;"What should I post today?"&lt;/p&gt;

&lt;p&gt;They're coming from questions you naturally encountered while trying to understand something.&lt;/p&gt;

&lt;p&gt;Those tend to make better articles.&lt;/p&gt;

&lt;p&gt;It changes how you read documentation&lt;/p&gt;

&lt;p&gt;Before I started writing more often, documentation was usually transactional.&lt;/p&gt;

&lt;p&gt;I had a problem.&lt;/p&gt;

&lt;p&gt;I searched for the answer.&lt;/p&gt;

&lt;p&gt;I copied the relevant mental model into my brain.&lt;/p&gt;

&lt;p&gt;Then I left.&lt;/p&gt;

&lt;p&gt;Now I notice more things.&lt;/p&gt;

&lt;p&gt;Why did the documentation explain this concept before that one?&lt;/p&gt;

&lt;p&gt;What misconception are they trying to prevent?&lt;/p&gt;

&lt;p&gt;Why is this warning here?&lt;/p&gt;

&lt;p&gt;What edge case was common enough that somebody decided it deserved an entire section?&lt;/p&gt;

&lt;p&gt;Good technical documentation isn't only teaching you the technology.&lt;/p&gt;

&lt;p&gt;It's showing you where people usually misunderstand it.&lt;/p&gt;

&lt;p&gt;That information is incredibly useful.&lt;/p&gt;

&lt;p&gt;It makes vague opinions harder to keep&lt;/p&gt;

&lt;p&gt;Developers have plenty of opinions.&lt;/p&gt;

&lt;p&gt;"This framework is slow."&lt;/p&gt;

&lt;p&gt;"Microservices are overkill."&lt;/p&gt;

&lt;p&gt;"SQL is better."&lt;/p&gt;

&lt;p&gt;"Serverless is expensive."&lt;/p&gt;

&lt;p&gt;"X is easier than Y."&lt;/p&gt;

&lt;p&gt;Those opinions are easy to say.&lt;/p&gt;

&lt;p&gt;They're much harder to publish when you know another developer can ask:&lt;/p&gt;

&lt;p&gt;Based on what?&lt;/p&gt;

&lt;p&gt;Writing forces you to qualify things.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;p&gt;Serverless is expensive.&lt;/p&gt;

&lt;p&gt;You start writing:&lt;/p&gt;

&lt;p&gt;Serverless can become expensive for workloads with these characteristics…&lt;/p&gt;

&lt;p&gt;Which is a much better statement.&lt;/p&gt;

&lt;p&gt;You stop trying to sound certain and start trying to be accurate.&lt;/p&gt;

&lt;p&gt;That's useful far beyond writing.&lt;/p&gt;

&lt;p&gt;You don't have to become a "content creator"&lt;/p&gt;

&lt;p&gt;This is probably the part developers hate.&lt;/p&gt;

&lt;p&gt;The moment somebody says:&lt;/p&gt;

&lt;p&gt;You should write.&lt;/p&gt;

&lt;p&gt;it starts sounding like:&lt;/p&gt;

&lt;p&gt;Build your personal brand. Post three times every day. Optimize engagement.&lt;/p&gt;

&lt;p&gt;I'm not talking about that.&lt;/p&gt;

&lt;p&gt;You can write once a month.&lt;/p&gt;

&lt;p&gt;You can have 20 readers.&lt;/p&gt;

&lt;p&gt;You can publish something that gets absolutely no traction.&lt;/p&gt;

&lt;p&gt;The value isn't only distribution.&lt;/p&gt;

&lt;p&gt;The process itself is useful.&lt;/p&gt;

&lt;p&gt;You are forcing your brain to turn:&lt;/p&gt;

&lt;p&gt;I think I understand this&lt;/p&gt;

&lt;p&gt;into:&lt;/p&gt;

&lt;p&gt;Here is exactly how I think this works.&lt;/p&gt;

&lt;p&gt;Those are very different things.&lt;/p&gt;

&lt;p&gt;The simplest writing habit I've found&lt;/p&gt;

&lt;p&gt;When something makes me stop while coding, I write it down.&lt;/p&gt;

&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;Things like:&lt;/p&gt;

&lt;p&gt;Why did this migration fail?&lt;/p&gt;

&lt;p&gt;Why does this API behave differently in production?&lt;/p&gt;

&lt;p&gt;Why are these two tools solving the same problem differently?&lt;/p&gt;

&lt;p&gt;Why does this configuration exist?&lt;/p&gt;

&lt;p&gt;What actually happens when this command runs?&lt;/p&gt;

&lt;p&gt;You don't need the article immediately.&lt;/p&gt;

&lt;p&gt;Just keep the questions.&lt;/p&gt;

&lt;p&gt;When you eventually sit down to write, you're not staring at a blank editor trying to invent a topic.&lt;/p&gt;

&lt;p&gt;You're answering something that genuinely made you curious.&lt;/p&gt;

&lt;p&gt;And curiosity is usually a better starting point than a content calendar.&lt;/p&gt;

&lt;p&gt;Writing is part of learning&lt;/p&gt;

&lt;p&gt;I used to think the sequence was:&lt;/p&gt;

&lt;p&gt;Learn → understand → write&lt;/p&gt;

&lt;p&gt;Now I think it's closer to:&lt;/p&gt;

&lt;p&gt;Learn → write → discover what you don't understand → learn more → rewrite&lt;/p&gt;

&lt;p&gt;And the loop keeps going.&lt;/p&gt;

&lt;p&gt;The article is almost a side effect.&lt;/p&gt;

&lt;p&gt;The real output is a clearer mental model.&lt;/p&gt;

&lt;p&gt;So if you're learning something, building something or repeatedly solving the same technical problem, try writing about it.&lt;/p&gt;

&lt;p&gt;Even if nobody reads it.&lt;/p&gt;

&lt;p&gt;You'll probably discover something you didn't know you didn't know.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>writing</category>
      <category>learning</category>
    </item>
    <item>
      <title>Your Backend Works Locally. That Doesn’t Mean It’s Production-Ready</title>
      <dc:creator>The Saint</dc:creator>
      <pubDate>Tue, 29 Sep 2026 00:07:56 +0000</pubDate>
      <link>https://dev.to/the_saint_dac63e343ee8704/your-backend-works-locally-that-doesnt-mean-its-production-ready-5g7l</link>
      <guid>https://dev.to/the_saint_dac63e343ee8704/your-backend-works-locally-that-doesnt-mean-its-production-ready-5g7l</guid>
      <description>&lt;p&gt;You finish the feature.&lt;/p&gt;

&lt;p&gt;The API responds correctly.&lt;/p&gt;

&lt;p&gt;The database connection works.&lt;/p&gt;

&lt;p&gt;Authentication passes.&lt;/p&gt;

&lt;p&gt;You run the app locally for the tenth time and everything looks fine.&lt;/p&gt;

&lt;p&gt;Then someone says:&lt;/p&gt;

&lt;p&gt;“Cool. Let’s deploy it.”&lt;/p&gt;

&lt;p&gt;And suddenly the problem changes completely.&lt;/p&gt;

&lt;p&gt;A backend that works on your laptop is not necessarily a backend that is ready for production.&lt;/p&gt;

&lt;p&gt;Local development proves that your application can run in your environment.&lt;/p&gt;

&lt;p&gt;Production asks a much harder question:&lt;/p&gt;

&lt;p&gt;Can this thing keep working when the environment is no longer under your control?&lt;/p&gt;

&lt;p&gt;That difference is where a lot of small teams get caught.&lt;/p&gt;

&lt;p&gt;Local development hides a lot&lt;/p&gt;

&lt;p&gt;Your development machine is unusually forgiving.&lt;/p&gt;

&lt;p&gt;You probably have:&lt;/p&gt;

&lt;p&gt;the correct environment variables&lt;br&gt;
direct access to the database&lt;br&gt;
the right runtime installed&lt;br&gt;
every dependency available&lt;br&gt;
full filesystem permissions&lt;br&gt;
a predictable network&lt;br&gt;
logs directly in your terminal&lt;br&gt;
one developer making requests&lt;br&gt;
a database you can reset without consequences&lt;/p&gt;

&lt;p&gt;Production gives you none of those guarantees.&lt;/p&gt;

&lt;p&gt;The application now needs to survive restarts, failed migrations, missing secrets, expired credentials, network interruptions, disk limits, bad deployments and actual users.&lt;/p&gt;

&lt;p&gt;That means “it runs locally” is only the beginning.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configuration becomes infrastructure&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Locally, this might be enough:&lt;/p&gt;

&lt;p&gt;DATABASE_URL=postgresql://localhost:5432/app&lt;br&gt;
JWT_SECRET=dev-secret&lt;br&gt;
PORT=3000&lt;/p&gt;

&lt;p&gt;In production, configuration has consequences.&lt;/p&gt;

&lt;p&gt;What happens if JWT_SECRET is missing?&lt;/p&gt;

&lt;p&gt;Does the application refuse to start?&lt;/p&gt;

&lt;p&gt;Or does it silently fall back to something unsafe?&lt;/p&gt;

&lt;p&gt;What happens when:&lt;/p&gt;

&lt;p&gt;process.env.DATABASE_URL&lt;/p&gt;

&lt;p&gt;is undefined?&lt;/p&gt;

&lt;p&gt;A production backend should fail predictably.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;const required = [&lt;br&gt;
  "DATABASE_URL",&lt;br&gt;
  "JWT_SECRET"&lt;br&gt;
];&lt;/p&gt;

&lt;p&gt;for (const variable of required) {&lt;br&gt;
  if (!process.env[variable]) {&lt;br&gt;
    throw new Error(&lt;br&gt;
      &lt;code&gt;Missing required environment variable: ${variable}&lt;/code&gt;&lt;br&gt;
    );&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;It is simple, but it is much better than discovering the problem after deployment.&lt;/p&gt;

&lt;p&gt;Configuration should be validated before the application begins accepting traffic.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Database migrations stop being harmless&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;During development, database changes are easy.&lt;/p&gt;

&lt;p&gt;Something breaks?&lt;/p&gt;

&lt;p&gt;Reset the database.&lt;/p&gt;

&lt;p&gt;Change the schema.&lt;/p&gt;

&lt;p&gt;Run the migration again.&lt;/p&gt;

&lt;p&gt;Move on.&lt;/p&gt;

&lt;p&gt;Production is different because the database contains data you cannot casually destroy.&lt;/p&gt;

&lt;p&gt;Imagine changing:&lt;/p&gt;

&lt;p&gt;ALTER TABLE users&lt;br&gt;
DROP COLUMN username;&lt;/p&gt;

&lt;p&gt;locally.&lt;/p&gt;

&lt;p&gt;No big deal.&lt;/p&gt;

&lt;p&gt;Now imagine doing that with 50,000 production users and discovering another part of the application still depends on username.&lt;/p&gt;

&lt;p&gt;The migration technically succeeded.&lt;/p&gt;

&lt;p&gt;The deployment still failed.&lt;/p&gt;

&lt;p&gt;Production migrations need to consider:&lt;/p&gt;

&lt;p&gt;backwards compatibility&lt;br&gt;
existing data&lt;br&gt;
rollback strategy&lt;br&gt;
application version compatibility&lt;br&gt;
long-running operations&lt;br&gt;
database locks&lt;/p&gt;

&lt;p&gt;For risky changes, the safer pattern is often incremental.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;p&gt;remove old field&lt;br&gt;
deploy new code&lt;br&gt;
hope&lt;/p&gt;

&lt;p&gt;you might:&lt;/p&gt;

&lt;p&gt;add new field&lt;br&gt;
deploy compatible code&lt;br&gt;
migrate data&lt;br&gt;
verify&lt;br&gt;
remove old field later&lt;/p&gt;

&lt;p&gt;The boring version is usually the safer version.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;“The server is running” is not a health check&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your process can be alive while your application is effectively dead.&lt;/p&gt;

&lt;p&gt;Maybe:&lt;/p&gt;

&lt;p&gt;PostgreSQL is unreachable&lt;br&gt;
Redis is unavailable&lt;br&gt;
migrations failed&lt;br&gt;
storage credentials are invalid&lt;br&gt;
an external dependency is timing out&lt;/p&gt;

&lt;p&gt;Your process manager may still happily report:&lt;/p&gt;

&lt;p&gt;RUNNING&lt;/p&gt;

&lt;p&gt;That is why production systems usually need an actual health endpoint.&lt;/p&gt;

&lt;p&gt;A simple example:&lt;/p&gt;

&lt;p&gt;app.get("/health", async (req, res) =&amp;gt; {&lt;br&gt;
  try {&lt;br&gt;
    await db.query("SELECT 1");&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;res.status(200).json({
  status: "healthy"
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;} catch {&lt;br&gt;
    res.status(503).json({&lt;br&gt;
      status: "unhealthy"&lt;br&gt;
    });&lt;br&gt;
  }&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;Now your infrastructure has something meaningful to test.&lt;/p&gt;

&lt;p&gt;Not:&lt;/p&gt;

&lt;p&gt;Is Node.js still running?&lt;/p&gt;

&lt;p&gt;But:&lt;/p&gt;

&lt;p&gt;Can this application actually serve requests?&lt;/p&gt;

&lt;p&gt;That distinction matters.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Logging changes when nobody is watching the terminal&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;During development:&lt;/p&gt;

&lt;p&gt;console.log(error);&lt;/p&gt;

&lt;p&gt;often feels perfectly adequate.&lt;/p&gt;

&lt;p&gt;You are already looking at the terminal.&lt;/p&gt;

&lt;p&gt;Production errors usually happen while nobody is looking.&lt;/p&gt;

&lt;p&gt;And this:&lt;/p&gt;

&lt;p&gt;Something went wrong&lt;/p&gt;

&lt;p&gt;is almost useless three hours later.&lt;/p&gt;

&lt;p&gt;Useful production logs should tell you things like:&lt;/p&gt;

&lt;p&gt;what happened&lt;br&gt;
when it happened&lt;br&gt;
which request triggered it&lt;br&gt;
which service failed&lt;br&gt;
how severe the failure was&lt;/p&gt;

&lt;p&gt;Structured logs are much easier to search and process.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;p&gt;console.log("Database error");&lt;/p&gt;

&lt;p&gt;something closer to:&lt;/p&gt;

&lt;p&gt;logger.error({&lt;br&gt;
  event: "database_connection_failed",&lt;br&gt;
  requestId,&lt;br&gt;
  error: error.message&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;gives you something you can actually investigate.&lt;/p&gt;

&lt;p&gt;Production observability is not about printing more text.&lt;/p&gt;

&lt;p&gt;It is about leaving enough evidence to understand failures after they happen.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Backups do not matter until restoration works&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A lot of systems technically have backups.&lt;/p&gt;

&lt;p&gt;Far fewer know whether those backups can actually be restored.&lt;/p&gt;

&lt;p&gt;There is an uncomfortable difference between:&lt;/p&gt;

&lt;p&gt;“We create a backup every night.”&lt;/p&gt;

&lt;p&gt;and:&lt;/p&gt;

&lt;p&gt;“We successfully restored yesterday’s backup into a clean database.”&lt;/p&gt;

&lt;p&gt;The second statement proves something.&lt;/p&gt;

&lt;p&gt;The first only proves that a file exists somewhere.&lt;/p&gt;

&lt;p&gt;A production backup strategy should answer:&lt;/p&gt;

&lt;p&gt;How often do backups run?&lt;br&gt;
Where are they stored?&lt;br&gt;
How long are they retained?&lt;br&gt;
Are they encrypted?&lt;br&gt;
How quickly can they be restored?&lt;br&gt;
When was restoration last tested?&lt;/p&gt;

&lt;p&gt;A backup you have never restored is still partly a hypothesis.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Deployment without rollback is a one-way door&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Imagine deploying version 1.8.&lt;/p&gt;

&lt;p&gt;Ten minutes later:&lt;/p&gt;

&lt;p&gt;error rates spike&lt;br&gt;
users cannot authenticate&lt;br&gt;
database queries slow down&lt;br&gt;
one endpoint starts returning 500&lt;/p&gt;

&lt;p&gt;What happens next?&lt;/p&gt;

&lt;p&gt;If the answer is:&lt;/p&gt;

&lt;p&gt;“Give me twenty minutes while I fix it.”&lt;/p&gt;

&lt;p&gt;you do not really have a recovery strategy.&lt;/p&gt;

&lt;p&gt;Sometimes the fastest fix is simply returning to the last known-good version.&lt;/p&gt;

&lt;p&gt;That requires your deployment system to know:&lt;/p&gt;

&lt;p&gt;v1.6&lt;br&gt;
v1.7&lt;br&gt;
v1.8 ← current&lt;/p&gt;

&lt;p&gt;and to make returning to:&lt;/p&gt;

&lt;p&gt;v1.7&lt;/p&gt;

&lt;p&gt;boring.&lt;/p&gt;

&lt;p&gt;Production reliability is not about never breaking anything.&lt;/p&gt;

&lt;p&gt;Eventually something will break.&lt;/p&gt;

&lt;p&gt;Reliability is largely about reducing how expensive failure becomes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Production traffic exposes assumptions&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;During local development you might be the only user.&lt;/p&gt;

&lt;p&gt;Production introduces:&lt;/p&gt;

&lt;p&gt;User 1&lt;br&gt;
User 2&lt;br&gt;
User 3&lt;br&gt;
...&lt;br&gt;
User 10,000&lt;/p&gt;

&lt;p&gt;And all of them can do things at inconvenient times.&lt;/p&gt;

&lt;p&gt;You start encountering problems like:&lt;/p&gt;

&lt;p&gt;race conditions&lt;br&gt;
exhausted database connections&lt;br&gt;
duplicate requests&lt;br&gt;
slow queries&lt;br&gt;
rate abuse&lt;br&gt;
concurrent writes&lt;br&gt;
memory growth&lt;br&gt;
unexpectedly large payloads&lt;/p&gt;

&lt;p&gt;For example, this query may seem harmless:&lt;/p&gt;

&lt;p&gt;SELECT *&lt;br&gt;
FROM orders;&lt;/p&gt;

&lt;p&gt;until orders contains several million records.&lt;/p&gt;

&lt;p&gt;Production has a habit of turning assumptions into benchmarks.&lt;/p&gt;

&lt;p&gt;A better definition of “done”&lt;/p&gt;

&lt;p&gt;For a backend feature, “done” should probably not mean:&lt;/p&gt;

&lt;p&gt;✓ Works locally&lt;/p&gt;

&lt;p&gt;A stronger checklist is closer to:&lt;/p&gt;

&lt;p&gt;✓ Works locally&lt;br&gt;
✓ Configuration validated&lt;br&gt;
✓ Database changes are safe&lt;br&gt;
✓ Authentication and permissions verified&lt;br&gt;
✓ Health checks available&lt;br&gt;
✓ Errors observable&lt;br&gt;
✓ Deployment reproducible&lt;br&gt;
✓ Backups exist&lt;br&gt;
✓ Restoration tested&lt;br&gt;
✓ Rollback possible&lt;br&gt;
✓ Production behavior monitored&lt;/p&gt;

&lt;p&gt;Not every side project needs enterprise infrastructure.&lt;/p&gt;

&lt;p&gt;But every application should know what level of failure it is prepared to tolerate.&lt;/p&gt;

&lt;p&gt;That is the important part.&lt;/p&gt;

&lt;p&gt;The backend lifecycle is bigger than building&lt;/p&gt;

&lt;p&gt;Developers spend a lot of time discussing how quickly we can create APIs, databases and authentication.&lt;/p&gt;

&lt;p&gt;Those things matter.&lt;/p&gt;

&lt;p&gt;But building the backend is only one stage.&lt;/p&gt;

&lt;p&gt;Eventually the lifecycle becomes:&lt;/p&gt;

&lt;p&gt;Build → Verify → Deploy → Operate → Own&lt;/p&gt;

&lt;p&gt;And the transitions between those stages are where a surprising amount of engineering time disappears.&lt;/p&gt;

&lt;p&gt;That is also the problem we have been thinking about while building CrescoDB: how to give smaller engineering teams a cleaner path through the backend lifecycle without forcing them to stitch together an increasingly complicated production stack.&lt;/p&gt;

&lt;p&gt;But regardless of which tools you use, the principle stays the same:&lt;/p&gt;

&lt;p&gt;A backend isn't production-ready because it runs. It's production-ready when you understand how it fails.&lt;/p&gt;

&lt;p&gt;What is the one production check you wish you'd added before one of your deployments went wrong?&lt;/p&gt;

</description>
      <category>programming</category>
      <category>node</category>
      <category>devops</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
