We had to ship a feature in two weeks that relied on MySQL auto-increment behavior. Problem: our production database was MySQL 5, which handles auto-increment differently than MySQL 8 after a restart.

The MySQL 8 migration was scheduled for two months out. We needed to ship now.

The “temporary fix” became permanent architecture improvement.

The Situation

We were building a resource allocation feature that tracked which resources were assigned to which entities.

The code assumed MySQL 8 auto-increment behavior: when the database restarts, auto-increment picks the largest existing ID and continues from there.

Reality: Production was running MySQL 5.

MySQL 5 behavior: After restart, auto-increment finds the first gap in the sequence and reuses IDs.

The problem:
When the database restarted, newly created resources could get the same ID as existing resources. This would break resource assignments across hundreds of services that relied on consistent IDs.

The timeline:

  • MySQL 8 migration: 2 months away (best case)
  • Feature deadline: 2 weeks
  • Impact if we shipped: Service disruption, resource allocation failures

Database restarts happen. “Service disruption” means pager alerts, incident calls, customer impact. Not acceptable.

The Obvious (Wrong) Choices

Option 1: Make it work with MySQL 5

Add logic to always pick the largest ID before inserting. This meant:

  • Expensive queries locking a high-traffic table
  • Complex code requiring extensive testing
  • Would miss the deadline
  • Pointless—MySQL 8 coming in weeks anyway

Option 2: Wait for the migration

  • Miss committed deadline
  • Delay value by 2+ months
  • Let database limitations block feature work

Option 3: Ship it and hope

  • Unacceptable risk
  • No control over migration timeline
  • Violates “don’t ship broken code”

None felt right. Time to question the premise.

The Better Question

Instead of asking: “How do we make this work with MySQL 5?”

We asked: “Why are we relying on auto-increment behavior at all?”

Over the years, I’ve learned the best solutions come from eliminating dependencies, not working around them.

The answer: No good reason. It was convenient, not necessary.

We were relying on auto-increment to pick IDs during insertion. But our unified resource table already tracked which IDs were in use. We could pre-allocate IDs for all resources—new and existing.

The Solution

Pre-allocate IDs for all resources in the unified table instead of relying on auto-increment at insertion time.

Before: Resources with no entity assignment had NULL entity IDs

Resource IDEntity A IDEntity B ID
103554NULL
1039NULLNULL

After: All resources get pre-allocated IDs for all entity types

Resource IDEntity A IDEntity B ID
1035541007
1039581009

Work required:

  • Data migration to pre-allocate IDs for existing resources
  • Modify resource creation logic (one function, one repo)
  • Total: One week of work

Result::

  • Works on MySQL 5 and MySQL 8
  • Ships on time
  • No database-specific dependencies
  • Simpler than waiting 2+ months a

Why This Was Better Than “Perfect”

The “quick fix” turned out to be better architecture:

More robust: Doesn’t depend on database-specific auto-increment behavior

More portable: Works across MySQL versions and other databases

Less fragile: No assumptions about gap handling or restart behavior

Simpler: Explicit ID allocation, no hidden behavior

We weren’t compromising. We were simplifying.

The Lesson

Constraints force clarity.

Without deadline pressure, we would have waited for MySQL 8, kept the fragile dependency, and missed the architecture improvement.

With deadline pressure, we questioned the dependency, found we didn’t need it, and shipped better code.

Over the years, I’ve seen this pattern: the “temporary workaround” that questions core assumptions often becomes permanent—because it’s actually better than the “proper” solution.

When You Hit Your Next Deadline

When you’re thinking “we don’t have time to do this right”, ask: “What if the ‘right’ solution is simpler than we think?” Look for the dependency you’re working around. Ask why you need it.

Often, you don’t.