DEV Community

Cover image for When AI Can Write Code Faster Than Us, Why Not Give Architecture a Safety Net?
Kent Phung
Kent Phung

Posted on

When AI Can Write Code Faster Than Us, Why Not Give Architecture a Safety Net?

Over the past couple of years, the way we write software has changed quite a bit.

AI-assisted development, AI coding, and “vibe coding” are becoming increasingly common. AI can generate features, write tests, refactor code, and even scaffold an entire service in minutes.

And honestly, as someone who is naturally lazy, I quite like that.

Less code to write, more time to think. :))

But after using AI in some real projects, I started thinking about another problem:

When code can be produced faster and faster, how do we keep the codebase from becoming a mess?

AI can ignore conventions, introduce unwanted dependencies, or simply misunderstand the architecture the team has agreed on.

We can put those rules into prompts, skills, coding guidelines, or documentation.

But I started wondering:

If we already have ways to test our code, why don't we do the same for architecture?

That was one of the reasons I started building Jet, and later ArchSafe.


It started with Hono

I know we already have NestJS — a well-known and powerful framework — but I wanted something lighter while still providing enough structure for larger applications.

Then I found Hono.

It's fast, TypeScript-first, supports multiple runtimes, and most importantly, it doesn't force developers into a specific application architecture.

I really like that freedom.

But as an application grows, the team still has to make a lot of decisions:

  • How should modules be organized?
  • Should services be allowed to access the database directly?
  • How should modules communicate with each other?
  • How should HTTP servers and background workers share infrastructure?
  • How do we prevent developers from accidentally breaking the architecture?

So I started building Jet, a modular backend framework on top of Hono.

The idea was pretty simple:

Keep the simplicity of Hono, while providing more structure for building larger backend applications.

I shared Jet with the Hono community before.

At that point, it was mostly an architectural experiment.

Then I started using it in real projects.

And that's when things started to change.


If we're already comfortable letting AI write unit tests...

There's been an interesting change in how I use AI.

I can now ask AI to implement a piece of code and then write the unit tests for it.

Or I can write the tests first and let AI implement the code until the tests pass.

That gives us a pretty useful safety net.

AI might get the implementation wrong, but if important business behavior is expressed in tests, we have something to verify it against.

It can be as simple as:

Requirement
     ↓
   Tests
     ↓
 AI writes code
     ↓
  Tests pass
Enter fullscreen mode Exit fullscreen mode

This makes me more comfortable using AI.

Not because I believe AI will always write the right code.

But because I have a constraint that can verify it.

And that made me wonder:

If we can do this for behavior, why don't we do the same thing for architecture?


Architecture needs a safety net too

Let's say a project has a simple rule:

routes
   ↓
service
   ↓
repository
   ↓
database
Enter fullscreen mode Exit fullscreen mode

If AI generates code that accidentally breaks this rule, you can spot it, tell the AI about it, and ask it to fix the code.

But in reality, we don't work alone.

You might be very careful about architecture, but can you be sure that every member of your team remembers every rule?

A new developer might not know them yet.

Someone trying to ship a feature quickly might skip them.

A pull request might contain hundreds or thousands of lines of code.

And reviewers are humans too.

Can you really expect reviewers to catch every architectural violation?

That's the problem that started to bother me.

We have a compiler to catch type errors.

We have linters to catch coding mistakes.

We have unit tests to protect business logic.

We have CI to automatically check all of these things.

So why is architecture often protected by nothing more than:

“Remember, don't do that.”

I think architecture needs a safety net too.

Instead of hoping that developers or AI will always remember:

routes → service → repository
Enter fullscreen mode Exit fullscreen mode

we can turn that into a rule that the system checks automatically.

If someone writes:

routes → database
Enter fullscreen mode Exit fullscreen mode

CI should be able to say:

Architecture violation:
routes.ts cannot depend on database.
Enter fullscreen mode Exit fullscreen mode

It shouldn't matter who wrote the code.

It shouldn't matter whether it was generated by AI or written manually.

The rules of the codebase should remain the rules of the codebase.

That's where ArchSafe started.


Turning architectural rules into constraints

ArchSafe is basically my attempt to apply the mindset of testing to architecture.

Unit tests help protect behavior.

Architectural rules help protect structure.

One answers:

“Does this code behave correctly?”

The other answers:

“Is this code being built the right way?”

For example, we can enforce:

routes.ts
    ↓
service.ts
    ↓
repository.ts
Enter fullscreen mode Exit fullscreen mode

while preventing:

routes.ts
    ↓
database
Enter fullscreen mode Exit fullscreen mode

ArchSafe can also enforce boundaries between modules and prevent shared infrastructure from depending back on feature modules.

The goal is simple:

Architecture shouldn't exist only in a developer's head or in a README.

Architecture should become a constraint of the codebase.


This becomes even more important when AI writes code

I don't think the problem is that AI writes “bad code”.

In fact, AI can write very good code.

The problem is that AI doesn't always know all the context and constraints of a codebase.

And when AI can generate hundreds of lines of code in seconds, reviewing every line to make sure all architectural rules are being followed becomes increasingly difficult.

So I don't think we necessarily need to make AI “smarter” so that it always gets everything right.

We can build strong enough safety nets so that:

when AI gets something wrong, the system can say “no”.

And this isn't only useful for AI.

It applies to every developer on the team.


Where Jet is today

After spending some time developing and using Jet in real projects, it has changed quite a bit from the first version.

A Jet application can be structured like this:

src/
├── index.ts
├── processes/
│   ├── http.ts
│   ├── worker.ts
│   └── scheduler.ts
├── modules/
│   ├── auth/
│   ├── users/
│   ├── orders/
│   └── payments/
└── shared/
    ├── config/
    ├── db/
    ├── auth/
    └── dto/
Enter fullscreen mode Exit fullscreen mode

Jet currently has three main process types:

                 Jet Application
                       │
        ┌──────────────┼──────────────┐
        ↓              ↓              ↓
      HTTP           Worker        Scheduler
Enter fullscreen mode Exit fullscreen mode

Some of the recent updates include:

  • Module scaffolding for HTTP, Worker, and Scheduler
  • Architecture enforcement with ArchSafe
  • Process isolation and lifecycle management
  • Graceful shutdown
  • Per-route rate limiting
  • Clearer configuration boundaries
  • A new documentation site
  • Improved production Docker workflow

These are things that came out of actually using the framework, rather than features added just for the sake of having more features.


Does AI make developers less important?

I don't think so.

I think AI is changing what developers need to focus on.

Previously, we spent a lot of time writing code.

Now AI can help us write that code much faster.

So architecture, system design, testing, and engineering principles may actually become more important.

The question is no longer only:

“How fast can AI build this feature?”

It is also:

“After 100,000 lines of AI-assisted code, does the codebase still have the architecture we started with?”

That's the problem I'm trying to explore with Jet.

Hono is the foundation.

Jet provides the application structure.

ArchSafe helps enforce architectural boundaries.

And I want to apply the same mindset we've already adopted with testing:

Don't just trust that the code will be correct. Build constraints that can verify it.


I'd love to hear your thoughts

Jet and ArchSafe are still evolving, and I'd really like to hear how other engineers approach this problem.

If you're using Hono, building TypeScript backends, or bringing AI into your development workflow:

  • How do you control AI-generated code?
  • Do you automatically enforce architectural rules?
  • Which rules do you think are actually worth enforcing?
  • How would you approach this differently?

If you have some time, I'd really appreciate it if you could give Jet or ArchSafe a try and share your feedback.

It could be a bug, an idea, something you think is unnecessary, or simply:

“I don't think this approach is right.” :))

All of it is useful.

Jet: https://github.com/khapu2906/jet

Jet Docs: https://jet-wheat-nine.vercel.app/#/

ArchSafe: https://archsafe.vercel.app/

Top comments (2)

Collapse
 
alexshev profile image
Alex Shev

Architecture needs a safety net because AI makes code volume cheaper than design correction. The useful guard is not a giant architecture document, but a small set of invariants that every generated change must preserve.

Collapse
 
khapu2906 profile image
Kent Phung

Exactly. I think the “small set of invariants” part is especially important.

I don't want ArchSafe to become another giant architecture documentation system that developers (or AI) have to remember.

The idea is to identify the few boundaries that really matter and make them machine-checkable.

For example:

route → service → repository

Then the important invariant is simply:

A route must not depend directly on the database.

Whether the code is written by a developer or generated by AI shouldn't matter — the constraint stays the same.

I think that's where architecture enforcement becomes really interesting in the AI era: we don't necessarily need AI to understand everything. We need the system to prevent it from breaking the things that matter.