Skip to main content
AI
8 min read
January 7, 2026

When to Let AI Generate vs. When to Architect by Hand

The Judgment Call Every Architect Faces Daily

Segev Sinay

Segev Sinay

Frontend Architect

Share:

The Judgment Call Every Architect Faces Daily

This is the question I get asked most often: "When should I use AI and when should I write it myself?"

The honest answer is that there is no universal rule. But after a year of making this judgment call daily — sometimes correctly, sometimes not — I have developed a framework that works. It is not perfect, but it saves me from the two worst outcomes: spending an hour on something AI could have done in a minute, and spending three days fixing something AI generated incorrectly.

The Decision Framework

I categorize every piece of work along two axes: structural complexity and contextual dependency.

Structural complexity is about the code itself. How many states does it handle? How many systems does it integrate with? How performance-critical is it?

Contextual dependency is about how much the code depends on information the AI does not have. Your team's conventions, your system's architectural patterns, your product's specific requirements, your users' specific needs.

                    High Contextual Dependency
                              |
                    ARCHITECT |  COLLABORATE
                    BY HAND   |  (Human leads, AI assists)
                              |
Low Structural ———————————————+——————————————— High Structural
Complexity                    |                Complexity
                              |
                    GENERATE  |  GENERATE WITH
                    FREELY    |  GUARDRAILS
                              |
                    Low Contextual Dependency

Let me walk through each quadrant.

Quadrant 1: Generate Freely

Low structural complexity + Low contextual dependency

This is the sweet spot for AI generation. The code is straightforward, and it does not depend on context the AI lacks.

Examples:

  • Utility functions (formatDate, capitalize, debounce)
  • Simple UI components following standard patterns (badge, avatar, tooltip)
  • Data transformation functions
  • API client boilerplate
  • TypeScript type definitions from JSON schemas
  • Basic CRUD form components
  • Standard layout components

For these, I prompt and ship. The code is simple enough that errors are obvious, and the patterns are common enough that AI generates them correctly almost every time.

// Perfect AI generation candidate
// Prompt: "Create a formatRelativeTime utility that takes a Date
// and returns a human-readable relative time string"

export function formatRelativeTime(date: Date): string {
  const now = new Date();
  const diffMs = now.getTime() - date.getTime();
  const diffSec = Math.floor(diffMs / 1000);
  const diffMin = Math.floor(diffSec / 60);
  const diffHour = Math.floor(diffMin / 60);
  const diffDay = Math.floor(diffHour / 24);

  if (diffSec < 60) return 'just now';
  if (diffMin < 60) return `${diffMin}m ago`;
  if (diffHour < 24) return `${diffHour}h ago`;
  if (diffDay < 7) return `${diffDay}d ago`;

  return date.toLocaleDateString();
}

Time saved: 5-10 minutes per function. Over a week, this adds up to hours.

Quadrant 2: Generate With Guardrails

High structural complexity + Low contextual dependency

The code is complex but follows well-known patterns. AI can generate it, but you need to be more careful.

Examples:

  • Complex form handling with validation
  • Data table with sorting, filtering, pagination
  • Authentication flow (standard OAuth/JWT patterns)
  • File upload with progress and preview
  • Complex but standard animation sequences
  • Multi-step wizards with state management

For these, I generate but review carefully. I specifically check:

  1. Edge cases — AI often handles the happy path well but misses edge cases
  2. Error handling — AI tends to be optimistic; production code needs pessimism
  3. Accessibility — AI generates ARIA attributes but often gets the semantics wrong
  4. Performance — AI does not optimize for render performance by default
// AI generates the structure, I verify the details
// Particularly: error boundaries, loading states,
// empty states, and accessibility

// What AI generates (good structure, needs review):
function DataTable<T>({ data, columns, onSort, onFilter }: Props<T>) {
  // ... complex implementation
}

// What I add after review:
// - Virtualization for large datasets
// - Keyboard navigation (arrow keys, Enter to select)
// - Screen reader announcements for sort/filter changes
// - Optimistic updates with rollback
// - Empty state and error state handling

Quadrant 3: Architect By Hand

Low structural complexity + High contextual dependency

The code itself is not complex, but it requires deep understanding of your specific system, team, or product.

Examples:

  • Routing architecture and page structure
  • State management architecture (what goes where)
  • Component hierarchy and composition patterns
  • Design system token definitions
  • Build configuration and optimization
  • Error handling strategy
  • API contract definitions
  • Feature flag integration patterns

These are deceptively simple. The code might be 50 lines, but those 50 lines encode decisions that affect the entire system. AI does not have the context to make these decisions.

// This looks simple but is pure architecture — do it by hand
// It encodes: team conventions, system boundaries,
// performance requirements, product roadmap

export const routeConfig = {
  public: {
    home: '/',
    pricing: '/pricing',
    blog: '/blog',
    blogPost: '/blog/:slug',
  },
  authenticated: {
    dashboard: '/app',
    settings: '/app/settings',
    projects: '/app/projects',
    projectDetail: '/app/projects/:id',
  },
  admin: {
    users: '/admin/users',
    analytics: '/admin/analytics',
  },
  api: {
    prefix: '/api/v1',
    // Why v1? Because we learned from the last project
    // that versioned APIs save pain during migrations.
    // This decision is contextual — AI would not know this.
  }
};

Quadrant 4: Collaborate (Human Leads, AI Assists)

High structural complexity + High contextual dependency

The most challenging category. The code is complex and context-dependent. Neither pure AI generation nor pure hand-writing is optimal.

Examples:

  • Complex business logic components
  • Performance-critical rendering with domain-specific optimization
  • Real-time collaboration features
  • Complex state machines (multi-step workflows with branching)
  • Integration layers between multiple systems
  • Migration code (old system to new system)
  • Accessibility-complex interactive widgets

For these, I architect the structure by hand and use AI for implementation details within that structure:

// Step 1: I architect the state machine by hand
// because I know the business requirements and edge cases

type WorkflowState =
  | { status: 'draft'; data: DraftData }
  | { status: 'review'; data: ReviewData; reviewer: string }
  | { status: 'revision'; data: RevisionData; feedback: string }
  | { status: 'approved'; data: ApprovedData; approvedBy: string }
  | { status: 'published'; data: PublishedData; publishedAt: Date };

type WorkflowEvent =
  | { type: 'SUBMIT_FOR_REVIEW' }
  | { type: 'REQUEST_REVISION'; feedback: string }
  | { type: 'APPROVE'; approvedBy: string }
  | { type: 'PUBLISH' }
  | { type: 'RECALL' };

// Step 2: I define the transitions by hand
// because wrong transitions = business logic bugs
const transitions: TransitionMap = {
  draft: ['SUBMIT_FOR_REVIEW'],
  review: ['APPROVE', 'REQUEST_REVISION'],
  revision: ['SUBMIT_FOR_REVIEW'],
  approved: ['PUBLISH', 'RECALL'],
  published: []
};

// Step 3: AI generates the reducer, UI components,
// and tests based on my architecture
// Prompt: "Implement a reducer for this state machine,
// and create React components for each state with
// appropriate actions available based on the transitions map"

This collaboration pattern — human architecture, AI implementation — is where I get the highest quality output.

The Time Estimation Heuristic

A practical heuristic I use: estimate how long the task would take by hand, and how long it would take to properly review AI-generated output.

  • If hand-writing takes 10 minutes and review takes 5 minutes → Generate
  • If hand-writing takes 30 minutes and review takes 25 minutes → Write by hand (the review time eliminates the benefit)
  • If hand-writing takes 2 hours and review takes 30 minutes → Generate with guardrails
  • If hand-writing takes 4 hours and review would take 3 hours → Collaborate (architect then generate)

The review time is often underestimated. Reviewing complex AI-generated code for correctness, edge cases, accessibility, and architectural fit is not free. For complex code, it can approach the time of writing it yourself.

The Experience Factor

One thing I have noticed: the benefit of AI generation scales with your experience, not against it. Junior developers get speed but risk quality. Senior developers get both speed and quality because they can:

  1. Write better prompts (they know what to ask for)
  2. Review output faster (they know what to look for)
  3. Catch architectural drift sooner (they have pattern recognition)
  4. Know when to reject generation entirely (they trust their judgment)

The most dangerous scenario is a junior developer generating code in Quadrant 3 or 4 — architecturally significant code that looks correct but encodes wrong decisions. If you are mentoring junior developers, teach them the framework. Help them recognize which quadrant they are in before they start typing prompts.

The Evolving Boundary

The boundary between "generate" and "architect" is not static. As AI tools improve, some things move from Quadrant 3 to Quadrant 1. As your codebase grows more complex, some things move from Quadrant 1 to Quadrant 4.

Revisit your assessment regularly. What needed hand-architecture a year ago might be safely generated today. What you generated freely last month might need more guardrails as your system has grown.

The goal is not to maximize AI usage or minimize it. The goal is to produce the best architecture in the least time with the highest confidence. Sometimes AI gets you there. Sometimes it does not. The judgment of when is what separates an architect from a code generator.

AI
Architecture
React
TypeScript
Performance
Design Systems
Accessibility
Junior Developers

Related Articles

Contact

Let’s Connect

Have a question or an idea? I’d love to hear from you.

Send a Message