Stop Being Afraid of Technical Debt

12 minute read

A belief I keep seeing among first-time founders and junior CTOs: technical debt is bad and should be avoided.

Nope. Technical debt is exactly like financial debt. It’s not moral. It’s not a sin. It’s a tool. Used well, it gives you leverage. Used poorly, it slowly kills you.

The real question isn’t “How do we avoid technical debt?” It’s “Where does taking on debt create leverage, and where does it silently destroy us?”

#Debt Done Right vs. Debt Done Wrong

Think about a credit card.

Using a credit card to buy groceries when you’re broke with no plan to pay it back? That’s bad debt. You’re just digging a deeper hole.

Using that same card to buy a laptop that lets you freelance and earn money? That’s good debt. The cost of capital is outweighed by the upside.

Startups work the same way:

  • Taking on financial debt to extend runway when the business model doesn’t work? Bad debt. You’re just delaying the inevitable and paying interest for the privilege.
  • Taking on debt when the model works and you’re using it to scale what’s working? Good debt. You’re pulling future value into the present.

Technical debt works exactly the same way. The challenge is knowing which kind of debt you’re creating — and whether there’s a realistic payback plan.

In finance, you see the interest rate on a statement. In code, the “interest” shows up months later as slow delivery, weird bugs, and painful incidents. By the time you feel it, it’s already expensive.

So the hard part in software isn’t “is debt good or bad in theory?” — it’s:

How do we tell upfront whether this is leverage-creating debt or wreck-the-foundation debt?

That’s not about raw intelligence. It’s about pattern recognition. It’s about scars.

#The Load-Bearing Beam Mental Model

Think about an architect designing a house. They know which beams are load-bearing and which walls are just cosmetic:

  • Cut corners on decorative molding? Fine. You can fix that later.
  • Use cheaper fixtures in the guest bathroom? Also fine. A homeowner can replace those without specialized skills.
  • Undersize the main support beams or mess up the foundation? Now every future change is a nightmare. Fixing it means tearing the house apart.

Software has the same structure.

Some things are load-bearing:

  • Core data models
  • Domain-critical subsystems (e.g., ledgers in fintech, telemetry in energy)
  • Authorization and identity in anything serious

Other things are non-structural:

  • Your first UI framework
  • Your initial choice of PaaS
  • Internal admin workflows

Experienced engineers know the difference because they’ve cut the wrong corners before and then lost months of their lives cleaning it up.

I’ve been through six startups across eight industries now. I’ve joined companies where the architecture was already built, and I’ve started greenfields from scratch. The biggest failures I’ve seen weren’t because people were dumb — they lacked the experience to recognize the load-bearing beams, and ended up taking on the kind of technical debt that eventually collapses the whole structure.

#Good Debt in Practice

At Texture, we’ve been very intentional about where we take on debt. Here are a few examples.

#1. RedwoodJS → Next.js: Shipping Fast, Then Rebuilding

In the early days of Texture, we were a developer platform. The dashboard existed for one reason: let customers log in and grab API keys.

I was the only person building it, and we had one job: ship something working, quickly.

So I used RedwoodJS. It was batteries-included, React-based, GraphQL-native. It let me move incredibly fast. And because design was absolutely not a load-bearing concern at that stage, I didn’t build a design system—I just used off-the-shelf Tailwind UI components. They were simple, clean, and good enough to get us on the field.

None of those choices mattered strategically. Our API and our data model were the foundation. The dashboard wasn’t.

Later, the business shifted.

Customers started logging in not just for API tokens, but to see:

  • their devices and sites,
  • their meters and customers,
  • their telemetry and events,
  • programs and dispatches on a map.

The dashboard went from “utilitarian UI for grabbing API keys” to “primary interface to the value we provide.” It became load-bearing.

That’s when we threw away the RedwoodJS/Tailwind UI version and rebuilt it with real architecture and a proper design system.

Was the first version technical debt? Absolutely. Did it create leverage? 100%. We bought speed when the UI didn’t matter, then paid it off when it became central.

#2. Render → AWS: Infrastructure as Intentional Debt

Another example of good technical debt: our early infrastructure choices.

Before Texture was even incorporated, one of our early engineers and I spent an entire day in a hackathon-style sprint trying to get AWS deployments wired up correctly. We got it working… but only because he was sitting next to me. As soon as he wasn’t around, I couldn’t reliably deploy anything myself.

That’s a terrible place for an early-stage CTO to be. If you can’t ship independently, you’re dead.

So I looked around for something simpler and found Render. Render gave me:

  • one blueprint YAML representing our whole architecture (🫶)
  • dead-simple automated deployments
  • zero infrastructure babysitting

It meant I could move fast on my own without depending on anybody else. So we ran everything on Render for about 18 months — intentionally. That was infrastructure debt, but it bought us velocity when we needed it most.

Later, when we started selling into enterprise utilities and SOC 2 became unavoidable, the math changed. Our compliance tooling (Vanta) automates deeply with AWS, not Render. Staying on Render would’ve forced a manual, paper-based audit at roughly 7× the cost.

So we migrated to AWS — not because Render was wrong, but because our customer demands and compliance needs evolved.

This is what good technical debt looks like: choose the fast path early, pay it down when the economics and constraints change.

#3. Slack as Workflow: Manual First, Automation Later

Early on, there were areas where we didn’t want to build full business logic, validation, and complex state transitions yet.

So when a user did something in the UI, instead of validating every edge case and building robust workflows, we:

  • posted a message into Slack,
  • had an engineer verify the state,
  • and updated the database manually.

Zero automation. Extremely “hacky.” 100% intentional technical debt.

But it let us:

  • validate which flows mattered,
  • understand the edge cases through human eyes,
  • and spend engineering time building customer-visible value instead of polishing internal plumbing.

Once we knew those flows were real and high-value, we built the proper workflows and retired the Slack hacks.

That’s the pattern of good technical debt: Intentionally cut a corner, watch it, then either pay it off or delete it.

(Note: Specific details in the following examples have been changed to protect the companies involved, but the core technical decisions and consequences remain accurate.)

#When Debt is Dangerous: Load-Bearing Mistakes

The scary kind of technical debt shows up when people cut corners on the foundation.

My favorite (awful) example: a consumer fintech startup I joined where the founding engineer, who was brilliant but inexperienced in this domain, built everything without a proper ledger.

This was software that moved real money:

  • debits and credits,
  • transfers in and out,
  • user balances,

…but:

  • No double-entry bookkeeping.
  • Money moved externally was tracked in a separate table.
  • Internal “balances” were derived indirectly.

Reconciling the flow of funds required duct-taping together multiple data sources and writing bespoke scripts. Simple questions like “How much money has this user moved?” or “What’s the true outstanding obligation?” were painful to answer.

We worked around it, but we spent months doing the kind of accounting archaeology that a proper ledger (open-source or something like Modern Treasury) would have made trivial.

That’s not “we chose the wrong JS framework.” That’s “we built a bank without a ledger.” That’s a load-bearing beam failure.

#The 18-24 Month Rebuild Philosophy

Here’s a view that tends to freak people out:

For systems under active development, I generally expect to burn them down and rebuild every 18–24 months.

We’ve already done this multiple times with our dashboard at Texture.

And it’s not because we were dumb two years ago. It’s because:

  • The product evolved.
  • The customer use cases changed.
  • We learned more about our domain.
  • And the codebase accreted inconsistent patterns that slowed everyone down.

Our current dashboard (as of writing) has:

  • legacy components copy-pasted forward from the previous version,
  • a dashboard-specific component library we built to move quickly,
  • and our proper design system, Edges, that we should be using everywhere.

We also have multiple patterns for data fetching and state management.

People experience this as “harder to change things” and “harder to find the right pattern.” But with modern AI tooling, it’s even worse: the model sees three different ways to do everything and frequently picks the wrong one.

  • You ask Claude Code or Cursor to add a feature.
  • It happily uses the old pattern, or the wrong design system.
  • You spend your time steering it back onto the “right” path.

A messy codebase is now a force multiplier for bad AI suggestions.

A clean rebuild with:

  • one design system,
  • one data-fetching pattern,
  • one way to handle state,

gives you back engineering velocity and maximizes AI-assisted productivity.

The point is not “we were mistaken before, therefore we must rewrite.” The point is:

You intentionally take on complexity and shortcuts to move fast, and you intentionally pay them down — sometimes by rebuilding — once the interest exceeds the benefit.

#The Rules You Can't Afford to Break

Over a couple of decades shipping software in anger, I've seen a few patterns that almost always hold:

#1. Data Models Are Load-Bearing

Your data model is one of the few parts of the system that becomes exponentially harder to change over time. It anchors your entire product surface area — APIs, permissions, workflows, analytics, billing, integrations, migrations, everything. If you get it wrong early, the “interest payments” show up everywhere.

One of the most common traps: assuming there is “one” of something when there will be “many.”

  • One product → later becomes product variants.
  • One account → later becomes account hierarchies.
  • One meter → later becomes multiple meters per site.

This is just one category of load-bearing data-model mistakes, but it illustrates the broader rule: it is much easier to design for flexibility up front than to retrofit it later.

Changing the model after it’s tied into persistence, APIs, background jobs, permissions, and reporting is painful, risky, and often business-disrupting.

Your UI can change weekly. Your infrastructure can change yearly. But your data model? That’s your foundation. Treat it like one.

#2. Store Core Data in the Right Place From Day One

Moving peripheral data stores later? Annoying, but survivable.

Getting the core wrong (or scattering it everywhere)? Brutal.

At Texture, where and how we map and store telemetry data from energy devices is a load-bearing decision. It touches everything: analytics, control, forecasting, program operations. We are extremely deliberate there.

But in the earliest days, not everything was load-bearing yet. For example, before “Site” was a first-class concept in our product, we stored a few site-related fields alongside device data. It let us move faster without building out the full multi-entity model upfront — the right pragmatism for that moment.

Months later, once “Site” became central to the product, that shortcut naturally turned into technical debt. At that point, unwinding it was painful, but it was also expected. We paid it down because the domain had evolved.

That’s the point: shortcuts are fine when something isn’t structural yet — but as soon as it becomes structural, you have to clean them up.

Something like our marketing site CMS? We can change that whenever. It’s not structural. Where your core data lives? That’s your foundation.

#3. Know Your Domain’s Load-Bearing Beam

Every domain has a few things you cannot screw up:

  • Fintech → ledgers and money movement.
  • Energy → telemetry integrity and control semantics.
  • Healthcare → compliant, auditable data storage.
  • Identity/security → auth and permission models.
  • E-commerce → inventory and order integrity.
  • Real-time systems → event ordering and idempotency.

And sometimes, the beams stack.

At Texture, we sit at the intersection of energy and real-time systems, which means our load-bearing beams include both:

  • telemetry correctness (energy domain), and
  • event ordering and idempotency (real-time/event-driven domain).

Those two constraints compound each other — a mis-ordered event or a non-idempotent handler isn’t just a bug, it can corrupt telemetry state, break dispatch logic, or cascade into downstream program operations. That’s why we’re meticulous there.

Everything outside the domain core is much more flexible. That’s where you spend your technical debt budget.

#Why Senior Engineers Are Worth the Money

This is one of the big reasons we built Texture around a simple philosophy I’ve written about before: fewer people, but better

A junior engineer:

  • often doesn’t see that they’re creating technical debt at all.

A mid-level engineer:

  • has heard “technical debt is bad,” so they try to avoid it everywhere and over-engineer things that don’t matter.

A senior engineer:

  • understands where debt is acceptable (and even desirable),
  • understands which beams are load-bearing,
  • and asks, every time: “What’s the leverage and what’s the payback plan?”

That intuition comes from having lived through the consequences.

It’s why we pay senior engineers well and why we’re unapologetic about it. The salary delta is tiny compared to:

  • the cost of refactoring a mis-modeled core system,
  • the drag imposed by a messy architecture built by people who didn’t know better.

This is especially true at the early stage, where:

  • every early architectural decision echoes for years, and
  • you’re trying to make the fewest, most correct bets you can.

Hiring a bunch of fresh grads because they’re “cheap” while they unknowingly pour structural technical debt into the foundation is often the most expensive decision you can make.

#What Founders and Investors Should Actually Ask

If you're a first-time founder or a non-technical CEO evaluating your CTO, here's the signal you want to look for.

Bad answers:

  • “We don’t really have technical debt.” (They don’t see it.)
  • “Technical debt is bad, we avoid it.” (They’re burning runway on perfection that doesn’t matter.)
  • “We move fast and hack; we’ll fix it later.” (There is no plan. “Later” never comes.)

Good answer:

Here are the areas where we’ve deliberately taken on technical debt, here’s why it created leverage, and here’s how and when we intend to pay it down.

As an investor, a great question to ask a CTO is:

Where have you taken technical debt, and what’s your payback plan?

You’ll know in 60 seconds whether they’re thinking like an architect or just pushing code.

#It's a Tool, Not a Threat

Technical debt isn’t inherently scary. It’s just a tool.

Used correctly, it:

  • accelerates your path to market,
  • helps you learn faster,
  • and lets you conserve expensive engineering cycles for the things that matter.

Used recklessly, it:

  • drives up the cost of change,
  • burdens every future decision,
  • and eventually forces you into painful, expensive rewrites under pressure instead of on your own terms.

The difference is experience — knowing which beams are load-bearing and which walls are just drywall.

The companies that win aren’t the ones with zero technical debt. They’re the ones that take it on intentionally, in the right places, and then pay it down ruthlessly before the interest gets crushing.

At Texture, that’s what we’re trying to do: take on debt where it creates leverage, pay it down when it starts dragging, and rebuild when the interest gets too high. It’s not perfect, but it’s fast — and in startups, fast usually wins.

If you’re one of those experienced engineers who gets this — who’s seen good debt and bad debt, who knows where the load-bearing beams are — we're hiring. Come help us build the right way.


Victor Quinn
Victor Quinn
Co-founder and CTO
Engineering leader with 20+ years scaling systems across 8 industries. Co-founder/CTO at Texture, building next-gen energy infrastructure. J.D. holder and technical architect who believes in code that ships and ships fast.

You've already got the data. Let's make it work.

Book a demo to explore how leading energy teams monitor usage, automate workflows, and collaborate in real time.