Hey everyone, Alex here. Welcome back to another edition of Coding with Alex at sysseder.com.
If you've spent any time on Hacker News recently, you probably saw a thread that got the entire community talking: "When Anyone Can Build Software, Who Decides What Not to Build?" It’s a philosophical question on the surface, but for those of us working in the trenches of software engineering, DevOps, and cloud architecture, it represents a massive, looming shift in our day-to-day reality.
We are rapidly moving from an era of software scarcity (where ideas were cheap, but engineering time was incredibly expensive) to an era of software abundance (where Large Language Models, AI agents, and low-code platforms can turn a natural language prompt into a functional microservice in seconds).
But here is the hard truth: just because an LLM can generate 50,000 lines of React and Go code to solve a hyper-specific business problem doesn't mean your organization should run, deploy, secure, and maintain it. In fact, our jobs as developers are shifting. We are transitioning from being pure "builders" to being "editors, architects, and gatekeepers." Let's dive deep into why this paradigm shift is happening, the hidden architectural tax of "easy" software, and how we can build automated guardrails to decide what not to build.
The Hidden Tax of Code Generosity
In the past, the friction of writing code served as a natural filter. If a feature or an internal tool wasn't truly necessary, the sheer cost of allocating two developers for a sprint usually killed it. Today, that friction is gone. A product manager, a junior dev, or even a non-technical stakeholder can spin up a prototype using tools like v0, Claude, or Copilot Workspace over a weekend.
However, code is not a physical asset; it is a liability. Every line of code written—whether by human hands or an LLM—carries a lifetime of hidden costs:
- The Maintenance Tax: Who patches dependencies when Snyk alerts you to a high-severity CVE in an AI-generated helper library?
- The Architectural Drift: When anyone can generate a microservice, you end up with "accidental microservices" that drift from your core domain-driven design, introducing latency and distributed system failures.
- The Security Attack Surface: Generative tools are notoriously bad at secure-by-default configurations. They write SQL injection vulnerabilities, hardcode secrets, and ignore proper CORS policies.
- The Cloud Bill: More services mean more container instances, bigger Kubernetes clusters, more NAT Gateway traffic, and higher database connection pools.
As senior engineers and architects, our primary value is no longer just writing code quickly. It is having the taste, experience, and foresight to say: "No, we shouldn't build this."
Shifting Our Mindset: From "How" to "Why"
To survive and thrive in this new landscape, we need to shift our architectural evaluation frameworks. When a new system design document or an AI-generated repository lands on your desk for review, you should evaluate it using three distinct lenses: Value-to-Maintenance Ratio, Domain Cohesion, and Operational Footprint.
1. Value-to-Maintenance Ratio
Before writing a single line of code, ask: Does this solve a core business problem, or is it a localized convenience? If a line of business wants an internal dashboard to track a metric that could easily be calculated in a spreadsheet or a BI tool like Metabase, generating a custom Node.js/React app is an anti-pattern. You are trading a 10-minute setup in an existing tool for years of dependency updates, hosting fees, and security audits.
2. Domain Cohesion
Does this new capability fit into our existing domain model, or does it create a redundant, parallel domain? If your AI tool generates a new service with its own isolated database schema for "User Profiles" just to support a minor feedback form, you are introducing data fragmentation and synchronization headaches. We must fight for the integrity of our data boundaries.
3. Operational Footprint
What is the operational cost of this software? Below is a conceptual diagram of how a "simple" generated microservice actually impacts your production infrastructure:
+-------------------------------------------------------------+ | Your Cloud Infrastructure | | | | +------------------+ (Ingress) +--------------+ | | | Public Gateway | --------------> | New Gen App | | | +------------------+ +--------------+ | | | | | | +----------------------------------+ | | | | (DB queries) | | | v v | | +------------------+ +--------------+ | | | Shared RDS / DB | | Log/Metrics | | | | (Conn Exhaust!) | | (Data Dog $) | | | +------------------+ +--------------+ | +-------------------------------------------------------------+
Even if the code was free to write, running it in production demands CPU, memory, database connections, log ingestion limits, and monitoring alerts. If not managed, your APM and cloud bills will skyrocket.
Automating the Guardrails: Policies as Code
We cannot rely on human reviews alone to stop the flood of generated code. We need automated guardrails that act as digital bouncers for our codebases and cloud environments. This is where Policy as Code (PaC) comes into play.
By using tools like Open Policy Agent (OPA), we can enforce architectural boundaries at the CI/CD level. Let's look at a practical example. Suppose we want to prevent developers (or AI agents) from deploying arbitrary microservices to Kubernetes unless they meet specific organizational standards (e.g., they must have an owner tag, resource limits, and be registered in our service catalog).
Here is an OPA policy written in Rego that checks a deployment configuration and rejects it if it doesn't meet our strict operational standards:
package kubernetes.admission
import rego.v1
deny[msg] {
input.request.kind.kind == "Deployment"
not input.request.object.metadata.labels["owner"]
msg := "Rejected: Deployments must have an 'owner' label specified for accountability."
}
deny[msg] {
input.request.kind.kind == "Deployment"
container := input.request.object.spec.template.spec.containers[_]
not container.resources.limits.cpu
msg := sprintf("Rejected: Container '%v' must have CPU resource limits configured.", [container.name])
}
deny[msg] {
input.request.kind.kind == "Deployment"
container := input.request.object.spec.template.spec.containers[_]
not container.resources.limits.memory
msg := sprintf("Rejected: Container '%v' must have Memory resource limits configured.", [container.name])
}
By implementing policies like this in your GitOps pipeline (using tools like Gatekeeper or Argo CD), you establish a hard technical boundary. An AI agent might be able to generate a deployment manifest in milliseconds, but it cannot bypass your engineering standards without human architectural approval.
The Solution: Build a "Paved Road" (Platform Engineering)
Simply saying "no" makes security and architecture teams look like progress bottlenecks. Instead, our goal should be to build a Paved Road (an golden path, as popularized by Spotify's platform engineering team).
If someone wants to solve a problem with software, we should provide them with highly opinionated, pre-approved templates that integrate seamlessly with our platform. If they deviate from the paved road, the operational burden shifts back to them.
For example, instead of allowing a developer to generate a custom Express.js API from scratch, provide a Backstage template that provisions a serverless function with built-in OAuth2, standardized logging, and automatic Terraform deployment. This ensures that even if software is built rapidly, it conforms to a highly controlled, secure, and maintainable blueprint.
Conclusion
The rise of generative AI doesn't threaten the job of the software engineer; it elevates it. The mechanics of typing code are becoming a commodity. The real value is shifting upstream to system design, API contract enforcement, security modeling, and infrastructure economics.
As code creation costs plunge to zero, the role of the senior developer is to ask the hard questions:
- Does this solve a fundamental business problem?
- Do we have an existing system that can do this with minor modifications?
- Are we ready to support this system for the next five years?
Remember: The cleanest, most secure, and most performant code you will ever write is the code you convinced your team not to build.
What do you think?
Are you seeing a flood of AI-generated code or unnecessary microservices in your organization? How are you setting up boundaries to manage this software abundance? Let me know in the comments below, or drop a line in our community Discord!
Until next time, keep your systems clean and your dependencies minimal.
— Alex