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 ID | Entity A ID | Entity B ID |
|---|---|---|
| 1035 | 54 | NULL |
| 1039 | NULL | NULL |
After: All resources get pre-allocated IDs for all entity types
| Resource ID | Entity A ID | Entity B ID |
|---|---|---|
| 1035 | 54 | 1007 |
| 1039 | 58 | 1009 |
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.