1,016 views
Every piece of PetBizApp — every client record, every booking, every invoice line — has to live somewhere specific, structured in a way that doesn’t break as the platform grows. That foundation is done: 50 distinct data types and 32 option sets, covering everything from client profiles to KPI tracking to team permissions.
It’s the least visible part of the build, and also the part everything else depends on. Get this wrong early, and you’re rebuilding from scratch later. We didn’t rush it.
Why Data Architecture Comes First, Not Last
There’s a real temptation, especially early in a build, to skip ahead to the parts users actually see and interact with: a nice calendar, a slick booking form, a polished client portal. Those are the pieces that generate visible progress and feel like real momentum. Data architecture is the opposite of that. It’s invisible to every eventual user of the finished product, it doesn’t demo well, and doing it carefully takes real time before any of the visible features can be built on top of it. We chose to do it first anyway, because the alternative, building visible features against an underspecified or inconsistent data model, tends to work fine for a demo and then fall apart as real usage and edge cases accumulate.
We’ve seen this pattern play out in other software before: a quick version ships, gains real users, and then the team discovers that a core assumption baked into the original data model doesn’t hold once the product needs to support a feature nobody anticipated at the start. At that point, fixing it means a genuinely disruptive migration, sometimes with real data loss risk, rather than a straightforward addition. Getting the foundation right before building the visible layer on top of it is slower up front and considerably safer over the following years.
What 50 Data Types Actually Covers
It’s worth being concrete about what “50 data types” actually means in practice, since the number alone doesn’t convey much. This covers the obvious core entities, clients, bookings, invoices, team members, but also a considerable amount of supporting structure that doesn’t get much visible attention: service definitions and their pricing variations, availability rules and exceptions, communication logs, document attachments, notification preferences, permission assignments, and the KPI framework’s own underlying tracking structures, among many others. Each of these needed its own clearly defined schema, its own relationship rules to the other data types it connects to, and its own validation logic before it could be considered genuinely finished rather than a rough first pass.
The 32 option sets serve a related but distinct purpose: standardized, controlled lists of values used across multiple data types, things like service categories, booking statuses, or communication channel types. Building these as shared, centrally managed option sets rather than allowing each individual feature to define its own ad hoc list of allowed values prevents a specific kind of drift that’s common in less disciplined software: one part of the app calling a status “completed” while another calls the equivalent state “done,” creating inconsistency that eventually confuses both the software and the people using it.
How We Approached Getting It Right the First Time
We didn’t just sit down and design 50 data types from first principles in isolation. Much of this work was informed by the same competitive research described in other build updates, looking closely at how established platforms like Time To Pet, Gingr, and others structure their own underlying data, where possible, and more importantly, talking directly with pet care business owners about the actual shape of their operations: how they think about a client relationship, what a single “booking” actually needs to represent given how flexible real scheduling arrangements often are, and where existing software they’d used had felt rigid or awkward because its underlying data model didn’t match how their business actually worked.
That research surfaced several specific decisions that shaped the final architecture. For example, we learned that many pet care businesses handle multi-pet households with genuinely different care needs per pet in ways that a simplistic one-client-to-one-pet data model would handle awkwardly. Our client and pet data types are structured to support a client with multiple pets, each with independent service history, care notes, and billing if needed, rather than forcing a workaround where a household with three dogs needing different services becomes three separate, disconnected client records.
The Trade-off We Accepted
Doing this work properly meant a genuinely slower start to visible feature development than we could have had by cutting corners here. Every milestone update in this build journal after this one is, in a real sense, built on top of the work described in this post. The scheduling engine, the KPI framework, the permission system, none of it could have been built with real confidence on a shakier foundation. We think that trade-off, a slower visible start in exchange for a foundation that won’t need a disruptive rebuild later, is the right one for a product meant to actually run real businesses’ operations for years, not just look good in an early demo.
Testing the Architecture Before Building On It
Before declaring this foundation genuinely complete, we ran it through a series of stress tests designed to surface gaps that wouldn’t show up in normal, well-behaved usage. This included populating the system with intentionally messy, edge-case data: clients with unusual household structures, bookings spanning midnight, service combinations that hadn’t been explicitly anticipated during design, and permission scenarios involving team members who’d changed roles partway through their tenure. Each of these tests was designed to break something, and where they did, we fixed the underlying data model rather than patching around the problem at a higher layer, since patching at a higher layer tends to just relocate the same underlying fragility rather than resolving it.
We also deliberately tested how the architecture would handle features we hadn’t yet built but could reasonably anticipate needing eventually, things like multi-location businesses, franchise-style team structures, or deeper integrations with third-party accounting software. We didn’t build support for all of these scenarios into the initial 50 data types, since that would have meant speculative complexity for features that may never ship in exactly the form we imagined. But we did confirm that the existing architecture could reasonably extend to accommodate them later without requiring a fundamental restructuring, which is a different and more achievable bar than trying to anticipate every possible future feature perfectly today.
What This Milestone Unlocked
With this foundation genuinely finished and stress-tested, every subsequent build milestone moved measurably faster than it would have otherwise. The core modules milestone that followed this one, covering Clients, Scheduler, Bookings, Invoicing, Team, and Messages, was able to focus entirely on user-facing functionality and interface design rather than simultaneously discovering and fixing data model gaps along the way. That’s really the clearest evidence that the upfront investment paid off: the pace of visible feature development accelerated once it had solid ground to build on, rather than continuing to slow down as complexity increased, which is the pattern you’d expect if the foundation had been rushed instead.
A Note on Documentation
Alongside the architecture itself, we wrote comprehensive internal documentation covering every one of the 50 data types and 32 option sets: what each represents, how it relates to the others, and the reasoning behind key design decisions like the multi-pet household structure mentioned above. This documentation isn’t something end users will ever see, but it matters enormously for anyone who works on PetBizApp’s codebase going forward, including future team members who weren’t part of these original design conversations. Undocumented architecture tends to become effectively unmaintainable over time as the reasoning behind specific decisions fades from memory and each subsequent change has to guess at intent rather than referencing a clear record of it.
Looking Back on This Decision
With several major features now built on top of this foundation, including the scheduling engine and the KPI framework described in other build updates, we remain confident this was the right sequencing choice, even though it meant a slower start on anything visible. Every foundation-level decision made carefully here has paid down real technical debt that would otherwise have accumulated silently and surfaced later, usually at the least convenient moment, as a feature that seemed simple turned out to require unwinding an underlying data assumption made in haste months earlier. We’d make the same choice again.
If you’re building software for your own business, whether that’s a pet care operation or something else entirely, the same principle applies more broadly than just to us: whatever data model underlies your day-to-day tools is worth getting right early, even if it means a slower start, because the cost of fixing it later only grows as more of the business comes to depend on it.
It rarely feels urgent in the moment, since the visible product still works fine on a shaky foundation for a while. The bill just comes due later, usually at a worse time than if it had been paid upfront.