I spent last week rebuilding how FarrierHub handles appointments, and it taught me something important about building systems that actually work.
The problem wasn’t with the appointments themselves—those worked fine. The problem was that I was thinking like software, not like a farrier.
The Moment Everything Clicked
Last Tuesday, I was sitting in my truck between barn calls, watching my phone battery drain while I tried to figure out the most efficient route to my next three stops. That’s when I realized I’d built the wrong thing.
FarrierHub was treating each appointment like an isolated event. But that’s not how farrier work actually happens. You’re not just showing up to one barn—you’re planning a route, optimizing travel time, and managing the logistics of getting from Point A to Point B efficiently.
The Database Migration That Broke Everything
So I started building a route management system. First step: migrate existing appointments into the new route structure.
The migration failed with this error: Error: no such column: a.barnId
Turns out, I’d been trying to access a column that didn’t exist. The appointments table only had horseId
and scheduledAt
—the barn information comes from the horse’s barn assignment through a separate relationship table.
This is exactly the kind of mistake that happens when you build features before you understand the data relationships. I’d been so focused on the UI that I hadn’t mapped out how the data actually flows through the system.
Building the Foundation First
After fixing the migration (and spending way too long debugging SQL queries), I focused on building the foundation properly:
- Route stops table with proper foreign key relationships
- Migration system that handles edge cases (appointments without barn assignments)
- Validation to prevent orphaned data
- UI components that work on a phone screen in varying light
The mobile-first design wasn’t optional—farriers work in the field, often with gloves on, in bright sunlight or dim barn lighting. Every interface needed to be touch-friendly and readable.
What Actually Works
Two weeks later, I have a route management system that actually makes sense:
- Route list screen with filtering and search that works on mobile
- Individual route details showing all stops for a given day
- Route optimization interface (basic version—the real optimization comes in Phase 3)
- Seamless navigation between routes and appointments
The key insight: simple beats complex every time. I’d initially planned to build real-time route optimization with mapping services, but that was over-engineered for the foundation. Better to get the basic structure right first.
The Real Takeaway
This wasn’t just about adding a feature to FarrierHub. It was about discovering a better pattern for how service-based businesses actually operate.
Most scheduling software treats appointments as isolated events. But that’s not how the work actually happens. Whether you’re a farrier, a plumber, or a delivery driver, you’re planning routes, not just showing up to individual stops.
The route management system demonstrates our approach at Steelbak: foundation first, real-world testing, and iterative refinement. Every decision is documented, every mistake is recorded, and every pattern is designed to be reusable.
Next up: field-testing the current implementation to make sure it actually works when you’re between horses, not just in the development environment. Then Phase 3—real optimization with mapping services and distance calculations.
But first, I need to stop building in the abstract and start testing with real barn schedules. Because the best systems aren’t built in isolation—they’re built in the field, where the work actually happens.