Skip to content

Why Architecture Matters More in the AI Era (Not Less)

Many people think that since AI can write code, architecture becomes less important.

The opposite is true.

I witnessed this firsthand when I ran an experiment with AI building a complex networking project. The results changed how I think about architecture in the AI era.

The Experiment

I asked an AI to build an HTTP benchmarking tool—a C-based project with epoll event loops, TLS encryption, multi-threading, and QuickJS embedding. Not a toy project. Real complexity.

Day 1 results:

  • ~2000 lines of working C code
  • Code compiled and ran
  • Achieved 140,000+ QPS (comparable to the industry-standard wrk tool)
  • All features functional

Everything worked. But when I examined the architecture, I found chaos:

What AI Produced:
- Connection layer embedded HTTP parser directly
- Each fetch() call created its own epoll instance (pseudo-async)
- Three different timer implementations coexisted
- Request types split into two unrelated hierarchies

The code worked perfectly. But I couldn’t modify it safely.

The Cost Equation Has Flipped

Here’s the core insight: AI has driven the cost of writing code close to zero. But the cost of managing complexity hasn’t changed at all.

Traditional Development:
Time spent:
+-- Architecture: 20%
+-- Coding: 60%
+-- Review/Testing: 20%
AI-Assisted Development:
Time spent:
+-- Architecture: 60% <-- MORE important
+-- Coding: 5% <-- AI handles this
+-- Judgment/Review: 35% <-- NEW focus

Without architectural guidance, AI generates what I call efficient technical debt machines. They work today. They’ll collapse tomorrow when you need to add a feature.

Why This Happens

AI writes code like a bricklayer laying bricks fast and well. But architecture is the blueprint.

Without blueprints, you get walls everywhere and no livable house.

I saw this clearly when the AI generated a connection structure:

ai-connection.c
// AI's approach: Everything piled together
typedef struct connection_s {
int fd;
int state;
http_parser parser; // HTTP knowledge embedded
char buffer[4096]; // Buffering mixed in
rbtree_node_t timer; // Timer implementation coupled
int request_type; // Request state scattered
void *request_data;
} connection_t;

This works. But every concern is tangled with every other. When the HTTP parser changes, the connection struct changes. When timer implementation changes, the connection struct changes. When I need to reuse connections for a different protocol, I’m locked in.

I gave the AI an architectural constraint:

“Separate concerns into distinct concepts. The connection layer shouldn’t know about HTTP.”

From this one sentence, the AI derived the refactoring:

proper-connection.c
// Proper layering with clear abstractions
typedef struct connection_s {
int fd;
int state;
} connection_t;
typedef struct http_peer_s {
connection_t *conn;
http_parser *parser;
buffer_t *in;
buffer_t *out;
} http_peer_t;
typedef struct timer_s {
rbtree_node_t node;
void (*handler)(void *data);
void *data;
} timer_t;

Now each concept is isolated. I can test each component independently. I can reuse the connection layer for WebSockets or custom protocols.

The Three Judgments AI Cannot Make

In my experiments, I identified three types of judgment that require human experience:

1. Judgment of Problems

The AI’s fetch implementation was pseudo-async—creating independent epoll instances per call. This isn’t a single-line bug. The entire I/O model is wrong.

AI doesn’t know this is a problem. I knew because I’ve done event-driven architecture at NGINX for years.

2. Judgment of Direction

When I said “global event loop + pending Promise,” this one sentence defined the entire async architecture direction. The AI correctly modified 9 files based on this constraint.

But that sentence itself requires experience. AI can execute direction. It cannot generate direction.

3. Judgment of When to Suspect

All tests were green. Functionality worked. At this point, most people would think “done.”

But I continued reviewing and found a subtle bug that would cause all 16,576 test cases to fail under specific conditions. Not because I’m smarter, but because experience tells me “when it looks too smooth, there’s often a problem.”

What Architecture Means in the AI Era

Here’s what confuses people about architecture:

# NOT architecture (AI can do this):
def process_request(request):
validate(request)
transform(request)
save(request)
# IS architecture (human must define):
# - Which layer owns validation?
# - How do layers communicate?
# - Where is complexity isolated?
# - What concepts deserve their own types?

The first is implementation. The second is design. AI excels at the first. Only humans can do the second.

The Quality Gap I Measured

After scoring both the AI-only code and the human-guided architecture, I found:

CategoryAI-OnlyAfter ArchitectureGap
Functionality8/108/100
Readability8/108/100
Async Design7/1414/14+7
Abstraction Quality5/99/9+4
Maintainability4/77/7+3
Code Organization5/88/8+3
Total59/10585/105+26

Notice: functionality and readability unchanged. The entire 26-point gap came from architectural dimensions.

Common Mistakes When Using AI for Development

I’ve made these mistakes. Learn from them:

Mistake 1: Trusting Tests Over Architecture

“All tests pass” proves nothing if the tests share AI’s blind spots. AI-generated tests for the HTTP tool checked that responses returned correctly. They didn’t check that the event loop could handle 10,000 concurrent connections without locking up.

Mistake 2: Reviewing Functionality, Ignoring Structure

Code reviews focus on “does this work?” and “is this readable?” They skip “does this fit our architecture?” and “will this scale?”

Mistake 3: Giving Solutions, Not Constraints

I’ve seen prompts like “add a connection pool.” AI adds one. But it’s the wrong abstraction for the problem.

Better: Say “we need to handle 10K concurrent connections with bounded memory” and let AI propose solutions. Then evaluate proposals against architectural principles.

The Shift in Developer Value

This isn’t about AI replacing developers. It’s about developers doing different work:

EraDeveloper FocusTime Distribution
1990s-2000sWriting code70% coding, 30% thinking
2010s-2020sWriting + Reviewing50% coding, 50% reviewing
2024+Architecture + Judgment10% coding, 90% judgment

The future developer doesn’t write functions. They make architectural decisions. They set constraints. They judge trade-offs.

The “Two Pizza Team” Rule (Amazon): Small teams can build big things. But only with clear architectural boundaries. AI amplifies this—small teams with AI can produce enormous amounts of code. Architecture becomes the limiting factor, not velocity.

Conway’s Law Revisited: “Organizations design systems that mirror their communication structure.” With AI, the communication structure is: human to constraint to AI to code. The architecture must be explicitly stated, not implicitly discovered through team interaction.

The Sapir-Whorf Hypothesis for Code: The language and abstractions we use shape how we think. AI thinks in patterns it has seen. If you want different architectural thinking, you must provide different architectural vocabulary.

What I Do Now

After these experiments, I’ve changed my workflow:

  1. Start with architecture diagrams before any code. Not detailed designs, but component relationships and data flow.

  2. Define constraints first: “The authentication module never touches the database directly” or “All external API calls have timeouts and retries.”

  3. Let AI implement within constraints: Give AI the boundaries and let it fill in the details.

  4. Review for architecture drift: Does the generated code respect the constraints? Often AI will “helpfully” violate a constraint because it saw a pattern in training data.

  5. Refactor before it grows: Don’t let AI add one more feature to a module that’s already doing too much.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments