How I Dropped the Production Database on a Friday Night

The case for moving fast and breaking things (before your competitors kill you)

The worst 7PM in my software engineering career

Picture this: It's a Friday evening in Paris, and I'm wrapping up what should have been a routine week at Joe AI, the real-estate startup where we were building an AI agent that automated communications for property developers across France.

I had just finished what I thought was a clean migration: moving our entire database from our old setup to PostgreSQL with Supabase. I had carefully designed a normalized schema with all the proper foreign keys to enable clean join queries. We were processing thousands of leads for a major French real-estate developer, and everything seemed to be humming along nicely.

Now, here's where I should mention a small detail: we were developing directly on the production database. You heard that right. No staging environment, no safety nets. Just pure, unfiltered startup velocity. We were early-stage, moving fast, and honestly? It felt like the right trade-off at the time.

That Friday, our big client couldn't update their user profile. Simple fix, I thought. I'll just delete their user record and recreate it with the correct fields. Clean slate, fresh start.

What I had forgotten, and this is where my "careful" database design came back to haunt me, was that our entire architecture relied on Row Level Security (RLS). Think of RLS as a security guard for your database: it controls which rows each user can access based on rules you set up. For example, you might create a rule that says 'users can only see leads assigned to their organization'. In our case, every single piece of data—leads, conversations, analytics, everything—was linked back to the users table through foreign keys to avoid unwanted access from other unauthorized users. This wasn't just for organization; it was our security model.

Example of a relational database schema where most entities are linked to the users table to restrict access to rows in the database. This example is taken from my simple auction SaaS Rankbid.

I clicked delete on that user record.

The database started acting strange immediately. Error messages from Supabase began flooding in in the top right corner of my screen. Surprised, I refreshed the page, hoping it was just a temporary glitch.

Nothing. Empty tables. Complete silence where three months of processed leads used to live.

"Oh no. Oh f*ck. What have I just done?". This was one of the most stressful moments in my entire life.

The CASCADE deletion had worked exactly as designed. When I deleted that user record, PostgreSQL dutifully followed every foreign key relationship and deleted everything connected to it. Three months of lead data, conversations, analytics—gone in a single SQL operation.

I immediately messaged my co-founders: "We have a situation."

Panic mode activated. I searched for backup options everywhere in the documentation, only to discover we were on Supabase's free plan. No automatic backups. The migration was recent enough that we had zero historical data anywhere else. You can imagine my stress level at that point.

After reading for minutes, I spotted it: Supabase's paid plans included daily backups. It was really unclear whether Supabase did backups even if you didn’t pay for the Pro plan, but at that point, $25 was a very small price to pay just for the hope of recovering some of the data. Without even asking my team for credit card details (everything was broken, time was critical), I threw my personal card at the upgrade and prayed those automatic backups existed.

Fortunately, they did.

Twenty minutes of the most stressful database restoration of my life later, we were back online. We'd lost 22 hours of data: everything since the previous night's backup, but I managed to backfill most of the critical records using our application logs (it took me 3 hours tho…).

Here's the technical takeaway: Never use CASCADE deletes on critical foreign keys. Set them to NULL or use soft deletes instead. It's fine for UPDATE operations, but it's too dangerous for DELETE ones. The convenience of automatic cleanup isn't worth the existential risk of chain reactions.

But here's what surprised me most about this disaster: it actually made us stronger as a team. That weekend, I spent hours setting up local Supabase instances for development. What started as damage control became a productivity breakthrough; we could now test features locally without the constant anxiety of breaking production (this might seems ridiculous to the most experienced, but we started from far). Ironically, my biggest screwup led to our most significant developer experience improvement.

“He, who has never broken the app, has never truly built”

When my manager at Joko said that, it felt like permission to take risks and try new things and I’ve never forgotten it. Small teams thrive on the freedom to ship, learn, and iterate; not on endless approval hoops.

In larger organizations, every outage triggers a postmortem and that’s valuable. But too often those learnings transform into more guardrails, more checkboxes, and soon you’re slower than your competition.

We acted like a scrappy startup at Joe AI: we broke production, learned fast, and then built better local workflows. Sure, I wish I’d set up local Supabase earlier, but missing that step is a small price to pay for the lessons we gained.

When you treat failures as experiments, never blaming the engineer but celebrating the attempt, you unleash true creativity. People take smart risks, speak up with ideas, and push the product forward.

Netflix’s co-founder Reed Hastings sums it up in No Rules Rules: give your team freedom and hold them accountable. When you trust people to break things, and to own the fix, you unlock innovations you never imagined. Remember: premature optimization and perfectionism are just procrastination in disguise. The real magic happens when you confront the market head-on and listen to actual user feedback. So ship boldly, learn quickly, and let every misstep fuel your next big win!