traacks.club

How We’re Approaching Schema Design for the New Traacks Web App

One of the first questions behind the new Traacks web app was whether to model all Supabase tables and types upfront or evolve them progressively as the product becomes clearer.

Introduction

As we build a new Traacks web app, one of the first questions we had was not about UI, branding, or even features. It was about data.

More specifically, we needed to decide how to structure the Supabase database from the start. Should we define all possible tables, relationships, and generated TypeScript types upfront? Or should we add them progressively as the product becomes more concrete?

That question matters more than it may seem. In an early-stage product, database structure affects almost everything: the API shape, front-end models, validation rules, access policies, migrations, and future maintainability. It also becomes more sensitive once real data starts to exist. Changing a schema on an empty project is easy. Changing it after users, records, and dependencies are already in place is a very different task.

For us, this was one of the first real architecture decisions behind the new Traacks platform. The challenge was to create enough structure to build with confidence, without locking ourselves too early into assumptions that the product might outgrow.

Engineering perspective

From an engineering point of view, the decision was essentially about schema strategy.

One option was to model everything upfront. That approach has clear advantages. It forces early clarity, gives the project a strong data foundation, and helps keep the codebase consistent from the beginning. With Supabase, it also means generated types can be established early and used across the application, which improves type safety in the front end and reduces ambiguity in queries, inserts, and updates.

The downside is that early certainty is often artificial. At the beginning of a product, many entities still exist as assumptions. Some tables look necessary until a workflow changes. Some relationships seem obvious until real usage reveals a different structure. If the initial schema becomes too broad, it can create friction: unused tables, premature abstractions, awkward joins, and types that reflect an old idea of the product rather than the current one.

The other option was to add tables and types along the way. That is usually more aligned with how products actually evolve, but it raises a valid concern: what happens once data already exists? Updating a live schema is possible, but it becomes more demanding. Each change may require migrations, backfills, renamed columns, compatibility handling, and updates to generated types across the application. The more tables and dependencies already exist, the more careful each change must be.

That concern was central in our discussion. We were not afraid of creating tables. We were thinking ahead about what happens when those tables start containing meaningful data and become tied to business logic, access rules, and front-end assumptions.

In practice, the most balanced approach is rarely “design everything now” or “improvise everything later.” It is usually a staged structure.

That means defining the stable core early, then letting the rest evolve with the product. The stable core is made of entities that are unlikely to disappear even if features change. These usually include foundational records, ownership relationships, authentication-linked profiles, and a few primary domain objects. Around that core, more specific tables can be added when workflows are validated and naming becomes clearer.

This approach also changes how migrations are treated. Instead of seeing schema changes as a sign of instability, they become part of the development workflow. Each migration documents an intentional step in the product’s evolution. Generated Supabase types can then be refreshed whenever the schema changes, keeping the application aligned with the database instead of drifting away from it.

The main technical goal is not to avoid change entirely. It is to make change controlled, traceable, and safe. A rigid early schema can slow down product discovery. A loose schema with no structure can create long-term maintenance problems. The engineering challenge is to find the point where the system is structured enough to stay coherent, while still flexible enough to evolve without costly rewrites.

Product perspective

From a product perspective, this was never just a database question.

It was a question about how much of the product we truly understood at that stage.

When a new application is still taking shape, it is easy to over-model the future. Teams often imagine every possible object, workflow, and edge case before real usage exists. That can feel productive, but it often leads to building for hypothetical complexity instead of present clarity. In practice, products become stronger when their data model follows validated needs rather than speculative ones.

That is especially relevant for a platform like the new Traacks web app, where the product vision is clear but many details become sharper only during implementation. We know the direction. We know the type of value the platform is meant to deliver. But some of the most important product decisions emerge while designing flows, testing assumptions, and identifying what users actually need to create, manage, or discover.

A progressive schema strategy supports that reality. It allows the team to keep moving without pretending every future structure is already known. It reduces the risk of spending time on data models for features that may later be simplified, merged, or removed. It also keeps the product closer to real use cases, because each new table or field is introduced in response to an actual need rather than a theoretical one.

There is also an operational benefit. Product teams work better when the system remains understandable. A leaner initial schema makes it easier to reason about the application, review decisions, and spot where complexity is starting to accumulate. That clarity helps not only developers, but also everyone involved in shaping the product.

Most importantly, this approach protects the product from false certainty. A new platform does not become stronger because every possible table exists on day one. It becomes stronger because the underlying model stays aligned with how the product is actually being used and refined.

In that sense, the right question was never “Can we define everything now?” The better question was “What do we know well enough to model with confidence today?” That shift matters, because it leads to a product that grows from validated structure instead of inherited guesswork.

Conclusion

One of the first real decisions behind the new Traacks web app was how to approach schema design in Supabase. The choice was not simply between planning and flexibility. It was about building a foundation that is strong enough to support development, without making the product carry decisions that are still too early to freeze.

Our concern about changing tables and types after data already exists was valid. Schema evolution does become harder once real records, logic, and dependencies are in place. But that does not mean everything should be designed upfront. It means the core should be deliberate, and the rest should evolve with discipline.

For a product still being shaped, that balance matters. The goal is not to avoid future migrations. The goal is to make sure each structural decision is grounded, useful, and timed correctly.

That is the direction we are taking with Traacks: define the parts that are stable, stay careful with assumptions, and let the platform earn its complexity as it grows.

Follow our journey on Traacks.