One Guard Away From Prod

A guard saved me from accidentally triggering an Azure Function in production. Why guards don't rely on your memory, and what they actually are.

I just saved myself from accidentally triggering something in production. And it wasn't because I was paying attention — it was because a while back, without knowing it would save me today, I added a guard.

A while ago I built a console app to manage Service Bus: full CRUD on queues and topics, receive, peek, send. From day one I added guards — one for writes (create, update, delete, send) and one for receive, just in case.


#The moment

Today, long after writing that code, I was on a call with a coworker, telling them exactly what I was about to test. I wanted to send a test message to a queue. I ran the send. The guard stopped me: writes disabled.

I checked which environment I was pointed at. Production. I wanted to test, and it didn't occur to me to check the environment before running the command.

What makes this worse than it sounds: that queue isn't an inert mailbox. It triggers an Azure Function. If the guard hadn't been there, I wouldn't have sent "a test message" — I would have kicked off a real production process, with everything that implies.


#You never know how far a safeguard's reach will go

When I added those guards, I wasn't specifically thinking "this will also save me from accidentally triggering a Function in production." I added them for a more generic reason: writing to Service Bus is dangerous, period. The safeguard ended up covering a much more specific and serious scenario than what I had in mind when I wrote it.

Anyone's a Nostradamus with Monday's newspaper. Today I can point to exactly what saved me and why. But when I wrote the guard, there was no way to anticipate this specific moment — only the general certainty that something, at some point, was going to go wrong.

That's the only honest way to design safeguards: not by trying to predict the exact incident, but by assuming you'll have one you can't predict.


#What is a guard, in practice?

Nothing magic: a boolean flag that enables or blocks the execution of a command or feature. If it's disabled, you show a message and stop there. If it's enabled, you continue.

It's the same mechanism as a Feature Flag — except here the goal isn't to gradually release a feature, it's to stop yourself before breaking something.

JSON
// appsettings.json
{
  "Guards": {
    "WriteEnabled": false
  }
}
CSHARP
public class GuardOptions
{
    public bool WriteEnabled { get; init; }
}

public class SendMessageCommand(IOptions<GuardOptions> guards)
{
    public async Task ExecuteAsync(string queue, string message)
    {
        if (!guards.Value.WriteEnabled)
        {
            Console.WriteLine("Write disabled by guard. Operation cancelled.");
            return;
        }

        // the actual send happens here
    }
}

#Two good practices, but only one doesn't depend on you

Checking the environment before operating is the obvious practice. Everyone knows it. The problem is it depends on you remembering, every single time, without exception — and today I didn't.

The guard doesn't depend on my memory. It's there, blocking by default, whether or not I remembered to check the environment.

The best defense against a future mistake isn't "pay more attention." It's designing the system so that attention isn't a requirement. Guards by default, not by exception.

A version of me from months ago, with no idea this was coming, saved today's me.

#guards #azure #service-bus #feature-flags