Are Feature Flags Bullsh*t? Why Your 'IF' is Killing Performance (and the Planet)

Published: (December 30, 2025 at 03:00 PM EST)
4 min read
Source: Dev.to

Source: Dev.to

Introduction

Let’s start at the beginning. How I arrived at this conclusion isn’t the point right now. For years I’ve been studying Computable Cognitive Architectures alongside Erlang, Elixir, and the Actor Model.

Recently I remembered a professor named Simão, whose research focused on the Notification Oriented Paradigm (NOP). Back then I didn’t fully grasp it. I had read a little, and while I still don’t claim to understand every detail today, I’ve begun to comprehend certain techniques that make immense sense—both in practice and in theory.

However, for something to be practical we must be open to a paradigm shift: the thought process, the idea, the architecture, and the design—everything changes.

Where the Actor Model Meets NOP

During my research I came across Fabio Negrini’s dissertation on NOPL Erlang‑Elixir technology. My takeaway? This paradigm proposes the reduction of those redundant ifs in a system that don’t make sense, allowing the execution flow to be as direct as possible.

“The answer is already no.”
If the system already knows a condition is false, why re‑evaluate that expression constantly?

The traditional implementation of feature flags introduces a silent technical debt: temporal redundancy. It is the repetitive re‑evaluation of an expression whose result remains unchanged for long periods. The software “asks” the same question millions of times, receiving the same answer.

In Elixir we are used to the Actor Model (isolated processes exchanging messages). NOP brings useful gossip to the table:

Actor ModelNOP
A process sends a message saying “do this” (a command).A process shouts a Fact (“Hey, my state changed!”). Whoever is interested can take action.

The Elements of NOP

Imagine transforming “dead” code into a living network where components talk to each other only when necessary. The structure of NOP is based on a graph of collaborative entities:

  1. Factual Entities (What the system “knows”)

    • FBE (Fact Base Element): Represents an object or concept (e.g., a User or a Sensor).
    • Attributes: The properties (e.g., the flag status). When an attribute changes, it proactively notifies those who depend on it.
  2. Logical‑Causal Entities (What the system “does”)

    • Premise: The smallest unit of decision. Unlike a common if, it only works when the attribute notifies it: “Hey, I changed!”
    • Condition & Rule: Group premises together. If satisfied, they trigger an Action via Instigation.

In the imperative paradigm (Java, C#, etc.) the CPU must evaluate every if inside a loop to see what changed. In NOP, premises are like stationary guards; processing only occurs at the “front line” where a change actually happened.

Hardware Sympathy: The Physical Cost of the “If”

Removing an if is a micro‑architecture optimization. Modern processors use deep pipelines and speculative execution (branch prediction).

  • The Problem: An if forces the CPU to “guess” the path. If it guesses wrong, a pipeline flush occurs, discarding work and wasting energy.
  • Green Coding: NOP eliminates billions of useless micro‑operations (load, compare, jump). This is energy savings at data‑center scale.

Implementation: Dynamic Compilation in Elixir

Using Elixir’s metaprogramming (Code.compile_quoted) and the BEAM’s hot code swapping, we can transform a configuration flag into a reactive recompilation. Instead of asking if a flag is active, the system is structurally altered to execute only the necessary code.

1. The Dynamic Compiler

defmodule FeatureCompiler do
  def recompile_module(feature_enabled?) do
    # The `if` is executed ONLY ONCE during recompilation.
    function_body =
      if feature_enabled? do
        quote do: NewPaymentProcessor.process(amount)
      else
        quote do: LegacyPaymentProcessor.process(amount)
      end

    module_ast =
      quote do
        defmodule PaymentProcessor do
          def process(amount) do
            unquote(function_body)
          end
        end
      end

    # Hot swapping on the BEAM
    [{module, binary}] = Code.compile_quoted(module_ast)
    :code.load_binary(module, ~c"nofile", binary)

    {:ok, module}
  end
end

2. The Notification Agent (FlagWatcher)

defmodule FlagWatcher do
  use GenServer

  def handle_cast({:update_flag, new_val}, _state) do
    # NOP Notification: Changed? Recompile!
    FeatureCompiler.recompile_module(new_val)
    {:noreply, new_val}
  end
end

Benchmark: The Numbers Don’t Lie

Approachips (iterations per second)Avg. time
Dynamic NOP (No if)311.993.21 ms
Traditional ifs32.1131.14 ms

Result: The NOP‑inspired approach was 9.72× faster.

Conclusion

The “Feature Flag is Bullsh*t” thesis is a warning against our own complacency. By applying NOP and the capabilities of the BEAM we remove temporal and structural redundancy. We transform passive configurations into reactive architecture.

Software doesn’t have to be a blind flow that asks the same question a billion times. It can be the exact manifestation of its current configuration.

So, will you keep wasting CPU cycles, or will you let you… (the story continues).

r system react only to what truly matters?

References

  • SIMÃO, Jean Marcelo. Paradigma Orientado a Notificações.
  • NEGRINI, Fabio. NOPL Erlang‑Elixir Technology: Notification Oriented Paradigm via an Asynchronous Micro‑Actor Approachlink.

GitHub: https://github.com/matheuscamarques/pon_feature_flag

Back to Blog

Related posts

Read more »