We Deleted 5,600 Lines of Code with Claude (and Found 1 Bug)

Published: (January 13, 2026 at 08:14 PM EST)
5 min read
Source: Dev.to

Source: Dev.to

The Over‑Engineered System I Built

I needed to manage providers (Google Cloud, AWS, Postgres) and their services (BigQuery, Firestore, DynamoDB). Seemed simple enough.

But I built this:

LocationWhat It Stored
seeds/sources_seed.goSource entities with services arrays
seeds/templates_seed.goConnectionTemplate entities with schemas
seeds/constants.goHard‑coded UUIDs
frontend/components/connections/index.tsUUID → Component mapping
frontend/components/connections/*.tsxHard‑coded selectedServices arrays
frontend/lib/services/google-cloud-capabilities.tsOAuth scopes per service
Database (Firestore)Sources and ConnectionTemplates collections

Eight+ files defining the same information in different ways.

  • Want to add a new provider? Touch 8 files.
  • Want to add a service to an existing provider? 6 files.
  • Want to understand how it all fits together? Good luck.

I told myself this was “flexible” and “extensible.”

The Realization

Then I actually thought about it:

  • Nothing was dynamic. OAuth scopes are locked at the OAuth app level. You can’t grant different scopes per connection—they’re baked into the OAuth consent screen.
  • There was no use case for partial service access. “This Google Cloud connection has BigQuery but not Firestore” – when would that ever happen? A connection is just credentials. If those credentials can’t access BigQuery, the API returns 401. Done.
  • I was maintaining complexity for flexibility I’d never use.

The “sophisticated” architecture was solving a problem that didn’t exist.

The Replacement: 20 Lines

I had no users yet, no backward‑compatibility concerns, and no data to migrate.

So instead of refactoring, I asked: What if I just deleted everything and replaced it with a single config file?

// frontend/lib/providers.ts
export const PROVIDERS = {
  'google-cloud': {
    name: 'Google Cloud Platform',
    auth: 'oauth2',
    services: ['bigquery', 'firestore', 'gcs', 'pubsub'],
  },
  'aws': {
    name: 'Amazon Web Services',
    auth: 'iam',
    services: ['dynamodb'],
  },
  'postgres': {
    name: 'PostgreSQL',
    auth: 'database',
    services: ['postgres'],
  },
} as const

export type ProviderId = keyof typeof PROVIDERS

That’s it—~20 lines replacing database tables, seeds, UUIDs, capability files, and registries.

Before → After Connection Model

Before: 6 fields, UUID lookups, redundant data

// Before
Connection = {
  id: 'abc123',
  sourceId: 'c7b3d8e9-5f2a-4b1c-9d6e-8a3b5c7d9e1f',   // UUID lookup
  templateId: 'template-google-cloud-oauth2',        // Another UUID
  services: ['bigquery', 'firestore'],               // Redundant
  connectionConfig: {
    selectedServices: ['bigquery', 'firestore'],     // Duplicate
    projectId: 'my-project',
  },
  credentials: { /* … */ }
}

After: 4 fields, string ID, no redundancy

// After
Connection = {
  id: 'abc123',
  providerId: 'google-cloud',           // Just the key from PROVIDERS
  config: { projectId: 'my-project' }, // Provider‑specific config
  credentials: { /* … */ }
}

How Claude Made This Possible

This wasn’t “let Claude write some code.” This was AI‑assisted architecture surgery.

1. Mapping the Blast Radius

I gave Claude the codebase context and asked it to find every file that referenced the old system. It identified:

  • All imports of the old types
  • All usages of the UUID constants
  • Frontend components using sourceId or templateId
  • Test files that would need updates
  • The order of operations to avoid breaking intermediate states

2. Systematic Execution

194 files is a lot to change by hand, and a lot to change correctly. Claude worked through them methodically:

Backend (Go)

  • connections/model.go – remove services, templateId; add providerId
  • connections/service.go – update creation/validation logic
  • connections/handler.go – update API request/response
  • connections/dao.go – update Firestore queries
  • router.go – remove /v1/sources/* routes
  • Delete entire sources/ package (9 files)
  • Delete entire connectiontemplate/ package (10 files)
  • Delete seeds/sources_seed.go, templates_seed.go

Frontend (TypeScript)

  • lib/providers.ts – new static config (the 20 lines)
  • Delete hooks/use-source.ts
  • Delete hooks/use-connection-template.ts
  • Delete services/source-service.ts
  • Delete services/google-cloud-capabilities.ts
  • Update 40+ component files that used the old types

3. Updating Tests in Lockstep

Key point: we didn’t delete tests; we updated them.

  • When we deleted the sources/ package, we also deleted its tests.
  • When we simplified the connection model, we updated the connection tests.

The test suite stayed green throughout the refactor.

Why Only One Bug?

After changing 194 files, we found exactly one bug in end‑to‑end testing. That’s not luck—it’s the result of:

  1. Comprehensive test coverage. Tests caught regressions immediately. When I changed the connection model, they told me exactly which handlers and services needed updates.
  2. Refactoring with tests, not after. Every change included corresponding test updates, keeping the suite reliable at every step.

Bottom Line

Over‑engineering can lock you into a maintenance nightmare. By stripping away unnecessary layers and letting AI help map the impact, I reduced a 5,600‑line system to a tidy 20‑line configuration—saving time, complexity, and future bugs.

Its Test Updates in the Same Commit

Tests weren’t an afterthought.

3. AI Helps You Be Systematic

Claude doesn’t forget to update a file in some distant corner of the codebase. It doesn’t get tired after file 80 and start making mistakes.

4. You Have a Clear Architectural Vision

I wrote a detailed plan document before touching code. The target state was unambiguous: one config file, string‑based provider IDs, no services arrays on connections.

What I Learned

Complexity Is a Choice

I built the complex system. Nobody forced me to create UUID‑based lookups and database seeds for static data. I did that because it felt “proper.”
Sometimes the proper solution is a 20‑line config file.

AI Is Best for Architecture, Not Just Autocomplete

The value wasn’t “Claude wrote code faster.” The value was:

  • Claude helped identify all the tentacles of the old system
  • Claude maintained context across 194 files
  • Claude was systematic where I would have gotten tired

Well‑Tested Code Enables Fearless Deletion

I could mass‑delete code because I trusted my tests. Every deletion was validated. No “I think this is safe” – either the tests passed or they didn’t.

No Users = No Excuses

Having no users yet meant I had no excuse to keep complexity around. No backward compatibility. No migration scripts. Just delete and move on.

If you’re early‑stage and carrying technical debt, now is the cheapest time to fix it.

The New Developer Experience

Adding a New Provider

  1. Add entry to PROVIDERS config (1 line)
  2. Create connection‑form component
  3. Create service‑config components
  4. Create backend handlers

Adding a Service to an Existing Provider

  1. Add to PROVIDERS[providerId].services array (1 line)
  2. Create service‑config components
  3. Create backend handlers

No seeds. No migrations. No UUIDs. No template entities.

Try It Yourself

If you’re staring at a system that feels heavier than it needs to be:

  • Ask what problem it’s solving. Is that problem real or hypothetical?
  • Check if anything is actually dynamic. If the “flexible” parts never flex, they’re just complexity.
  • If you have good tests, trust them. They’ll catch your mistakes.
  • Use AI to map the blast radius. It’s better at finding all the references than you are.

Sometimes the answer is mass deletion.

Have you ever deleted a system you built because you realized it was over‑engineered? What helped you make that call?

Back to Blog

Related posts

Read more »

𝗗𝗲𝘀𝗶𝗴𝗻𝗲𝗱 𝗮 𝗣𝗿𝗼𝗱𝘂𝗰𝘁𝗶𝗼𝗻‑𝗥𝗲𝗮𝗱𝘆 𝗠𝘂𝗹𝘁𝗶‑𝗥𝗲𝗴𝗶𝗼𝗻 𝗔𝗪𝗦 𝗔𝗿𝗰𝗵𝗶𝘁𝗲𝗰𝘁𝘂𝗿𝗲 𝗘𝗞𝗦 | 𝗖𝗜/𝗖𝗗 | 𝗖𝗮𝗻𝗮𝗿𝘆 𝗗𝗲𝗽𝗹𝗼𝘆𝗺𝗲𝗻𝘁𝘀 | 𝗗𝗥 𝗙𝗮𝗶𝗹𝗼𝘃𝗲𝗿

!Architecture Diagramhttps://dev-to-uploads.s3.amazonaws.com/uploads/articles/p20jqk5gukphtqbsnftb.gif I designed a production‑grade multi‑region AWS architectu...