The Problem

When I joined BooksOpen as founding engineer, the platform had a fundamental architectural limitation: one user, one workspace. Each service provider had their own isolated studio—their own calendar, settings, and bookings.

This worked fine for solo practitioners. But as our users grew, so did their needs. Tattoo studios wanted multiple artists sharing the same calendar. Piercing shops needed several piercers under one studio. The market was telling us: teams need to work together.

The ask was clear: enable multiple service providers to share the same workspace while maintaining their individual accounts.

The Technical Challenge

This wasn't a simple feature addition—it was a full schema redesign plus a completely new payment infrastructure.

Our stack:
- Next.js (frontend)
- Nest.js (backend)
- Prisma (ORM)
- PostgreSQL (database)

The original schema assumed user_id was the primary key for everything. Bookings, settings, calendar events—all tied directly to a single user. And since it was a 1-1 structure, payments were simple: each service provider received their own money directly.

But with multiple providers sharing a workspace, the payment flow needed to change completely. A tattoo studio owner should receive money from their own appointments and from their artists appointments. We needed automatic payment splits and transfers.

This meant implementing Stripe Connect from scratch—enabling connected accounts so BooksOpen could automatically transfer funds to workspace admin bank accounts, handling the revenue from the entire team.

The new model needed a workspace entity sitting between users and their data:


Before: User → Bookings, Settings, Calendar
After:  User → Workspace → Bookings, Settings, Calendar
             ↑
       Other Users


Every table needed restructuring. Every query needed updating. Every API endpoint needed to understand the new relationship.

The Migration Strategy

With 500,000+ records in production, we couldn't afford mistakes.

We chose a big bang release over incremental migration. Why? The schema changes were too interconnected. Half-migrated data would create more bugs than it solved.

The plan:
1. Build the entire new architecture in parallel
2. Write a comprehensive migration script
3. Test extensively on production-like data
4. Deploy during lowest traffic window

We scheduled the migration for 1 AM—when traffic was at its lowest. The migration script ran until 5 AM, transforming every record to the new structure.

The Results

The migration was a success:

- 15+ features shipped simultaneously
- All existing functionality preserved
- Zero data loss across 500k+ records
- Team workspaces finally enabled
- Stripe Connect implemented for automatic team payment splits

Service providers could now invite colleagues to their studio. Shared calendars. Shared settings. Individual accounts. And most importantly—workspace admins could now receive revenue from their entire team's appointments automatically, with funds flowing straight to their bank account via Stripe Connect.

The architecture finally matched what the market needed.

The Lesson

Here's what I'd tell anyone facing a similar migration:

You don't need to know everything before you start.

In Brazil, we have an expression: "No andar da carruagem, as melancias se ajeitam"—roughly, "the watermelons will arrange themselves as the cart moves."

I spent weeks trying to map out every edge case before writing code. But the real edge cases? They only revealed themselves once I started building.

Start with what you know. The details you're missing will surface naturally as you move forward. Waiting for perfect clarity is just procrastination in disguise.

The 3-month timeline wasn't because the work was slow—it was because I finally trusted the process and let the problems come to me instead of trying to predict them all upfront.

Key Takeaways

1. Architecture changes compound — A 1-1 to 1-N migration touches everything. Plan for full schema redesign.

2. Big bang can work — When changes are too interconnected, incremental migration creates more problems than it solves.

3. Time your deployment — We ran a 4-hour migration at 1 AM. Know your traffic patterns.

4. Test on real data volumes — 500k records behave differently than 500. Test at scale.

5. Start before you're ready — Perfect knowledge is a myth. Build, learn, adapt.