Back to Blog
securitydata-isolationleast-privilegetrustconsulting

Client Data Isolation: Why I Give Every Client Their Own Database

How I handle client business data as a consultant: per-tenant database isolation, read-only Shopify scopes, and short-lived tokens. Trust as the baseline.

By Mike Hodgen

Short on time? Read the simplified version

The Moment a CEO Hands You Their Books

A few months ago a CEO running an e-commerce brand asked me to audit their numbers. Orders, customers, revenue, the works. To do that I needed access to the systems where all of it lived.

There's a question every CEO asks when they grant that access, even if they don't say it out loud: where does this data go, and who else can see it.

Most consultants answer that question badly without even realizing it. They pull everything into a shared analytics workspace because it's faster. One database, one dashboard, every client's data in the same place. It saves setup time and it's the default most people reach for.

It's the wrong default. And it's exactly the kind of shortcut that should make a CEO nervous.

When I pulled this brand's orders, customers, and revenue, it went into a place that touches no other client's data. Ever. Not a shared table with a client ID column. Not a multi-tenant schema with row-level policies holding the wall up. A dedicated instance that holds their data and nothing else.

This is what I mean by client data isolation, and it's the thing I want to walk through in this article, because it's the part of the work nobody markets and everybody should ask about.

Isolation isn't a premium tier I upsell. It's the baseline. It's the thing that earns the right to touch a business's books in the first place.

If you're going to hand someone your customer list and your revenue numbers, the way they store that data tells you everything about whether you should trust them with it. So let me show you how I do it, and why I refuse to do it any other way.

Why a Shared Analytics Store Is a Liability, Not a Convenience

The common pattern is to load every client into one database. It's convenient. One place to query, one dashboard to maintain, one set of credentials to manage. I understand the appeal.

It's also a liability that the client pays for and the consultant pockets the convenience on.

The breach blast radius problem

Here's the math that matters. When you put 20 clients into one shared store, a single compromised credential exposes all 20. That's the blast radius.

Comparison showing a shared database where one leaked credential breaches all 20 clients versus isolated instances where a breach is contained to a single client Shared store blast radius vs isolated instances

One leaked connection string. One misconfigured access policy. One laptop left unlocked at a coffee shop. In a shared store, that single event isn't one breach. It's 20 breaches at once.

I've spent a lot of time inside fast-built systems, and the security debt I find auditing fast builds almost always traces back to this kind of shortcut. Speed today, exposure later. The convenience of one dashboard gets paid for with everyone's exposure.

The confidentiality problem

Then there's the quieter problem. Even with no breach, client A's revenue, customer emails, and order history are sitting next to client B's. That's a leak waiting to happen.

A bad query that forgets a filter. A debugging dump that pulls the whole table. A row-level policy that looked right but had a gap nobody tested. Any one of those quietly hands one client's data to another, and you might not even know it happened.

I've watched these failures show up in real systems. They're not exotic. They're the boring, predictable result of putting data that should never meet in the same room.

So I made a decision early. I will not be the single point of failure across multiple businesses. The data each client trusts me with does not get to sit next to anyone else's. That's not a feature. It's a refusal.

Per-Tenant Database Isolation: One Brand, One Instance

Let me get concrete about what I actually built for that e-commerce audit, because the principle only means something when you can see the mechanism.

What dedicated means in practice

For this brand I stood up a dedicated database instance (Supabase-class, if you want the category) that held only their data. No shared tables. No shared schema. No co-tenancy with another client.

This is per-tenant database isolation in its strongest form. It's not one database with a tenant column separating everyone. It's one database, period, for one client. When the engagement involves another client, that's a separate instance entirely, with its own credentials and its own walls.

I've written before about why I treat data isolation as a default rather than something you bolt on when a client gets large enough to ask for it. The default matters because defaults are what you fall back to when you're moving fast, and moving fast is when mistakes happen.

Zero code imports across projects

The isolation goes past the database. Each client's project is its own codebase with zero imports from any other client's project.

Architecture diagram showing three clients each with their own separate codebase, credentials, and database instance, with no shared imports between them Per-tenant isolation architecture with separate codebases

This matters more than it sounds. Shared code is how secrets travel. A connection string in a shared utility file, an API key in a config that two projects import, a credential helper that "we use everywhere." That's the path leaks take across boundaries. They don't hop over walls. They ride along on shared code.

So I keep the codebases separate the same way I keep the data separate. I also audit my own work for exactly this kind of leak. Here's how I audit my own codebases for leaks, because writing the policy is easy and actually living by it is the hard part.

The principle is simple to state and harder to hold: the data never lands in a shared store, full stop.

I'll be honest about the tradeoff. This is more setup per client. A new instance, a new isolated project, fresh credentials, separate everything. It's slower than dumping everyone into one place. I've decided that's non-negotiable, and the extra setup time is the cost of being trustworthy with someone's books. I'd rather eat that cost than make my clients eat the risk.

Read-Only API Scopes: Take Only What You Need to See

Isolation handles where the data lives. The next question is what I'm even allowed to do with it.

Why read-only Shopify scopes matter

For an e-commerce audit I need to read orders, customers, and revenue. That's it. I never need to write a record, issue a refund, or delete anything in the store.

So the access I request matches that exactly. Read-only Shopify scopes, nothing more. I don't ask for write permission "just in case." I don't request the broad scope because it's easier to set up once. I ask for the ability to read the specific things the work requires, and nothing past that line.

The mechanism underneath is a client-credentials grant, and here's what that means without the jargon. The app proves who it is, and in exchange it gets back permission to read, not permission to act. The store knows exactly what this access can and cannot do, because the scopes define it.

Least privilege as a posture, not a checkbox

The benefit to the client is concrete. Even if my access were somehow compromised, the attacker could read the store but could never modify it. No fraudulent refunds. No deleted orders. No tampering with customer records. Read access leaks are bad, but they're a different universe from write access leaks.

Least privilege gets treated like a compliance checkbox most places. Tick it, move on. I treat it as a posture instead. You ask for the minimum, every single time, and you build the habit so you don't drift toward "just give me admin" when a deadline is close.

The proof is that I can show the client exactly what my access can and can't do. Not describe it vaguely. Show it. The scope list is right there. If it says read and not write, that's not a promise, it's a boundary the platform enforces.

Short-Lived Tokens: Access That Expires by Design

Read-only access is good. Read-only access that also expires is better. This is where short-lived token security comes in, and it's the piece most setups skip.

The 24-hour token refresh pattern

Instead of holding a permanent API key, the system exchanges credentials for a short-lived token that lasts about 24 hours. Each run refreshes it. The token does the work, then it expires.

So the actual thing sitting in memory while I run an audit isn't a permanent key to the store. It's a token with a one-day shelf life. If that token leaks somehow, it's useless within a day. The window where stolen access is worth anything is small by design.

Why long-lived credentials are the real risk

Contrast this with the pattern that shows up in breach reports over and over: a long-lived API key sitting in a config file for months. Maybe years. It works, nobody touches it, everybody forgets it's there. Then it ends up in a git history, a backup, a screenshot, a logged error message, and now it's a permanent skeleton key that opens the store forever.

Timeline comparing a self-refreshing 24-hour token that expires daily against a permanent long-lived API key that becomes a permanent security risk Short-lived token lifecycle vs long-lived key risk

Long-lived credentials are the real risk. Not because they're more powerful, but because they don't expire. Time is on the attacker's side. A key that works forever only has to leak once.

A short-lived token flips that. Time is on the client's side instead. And the client keeps the master switch the whole way through. They can revoke the underlying credential at any moment, and when they do, my access dies. Not after I acknowledge it. Immediately.

This is what "trustworthy with your books" looks like as a mechanism, not as a line on a sales page. Anyone can say they're careful. This is the wiring that makes it true.

What the CEO Actually Gets From This

Let me translate all of this out of engineering and into what you actually receive as the person handing over the data.

The trust you can verify

You get three things, and none of them are features I charge extra for.

Vertical infographic listing the three verifiable guarantees a client receives: isolated data, read-only access, and daily-expiring tokens What the CEO gets, three verifiable guarantees

Your data never co-mingles with anyone else's. It lives in an instance that's yours alone, so there's no neighbor's bad query that can reach it and no shared breach that takes you down with 19 strangers.

My access is read-only, so I can look but I can't touch. I can't damage your store, can't move money, can't delete a thing. The platform enforces that, not my good intentions.

And my access expires daily, so a leaked token has a one-day shelf life and you can kill the underlying credential whenever you want.

What I can prove if you ask

Here's the part I want you to hold onto. You should be skeptical of anyone who wants broad, permanent, write access to a shared system. That combination, broad plus permanent plus shared plus write, is the worst case on every axis at once.

A four-axis matrix showing the worst-case combination of broad, permanent, shared, write access versus the safe baseline of minimal, short-lived, isolated, read-only access The four-axis worst case for evaluating a consultant

Any consultant who can't describe their isolation model in plain terms hasn't thought about it. That's not a gotcha. It's a real filter you can use. Ask the question and listen to whether the answer is specific or hand-wavy. The specifics are the whole point, because vague is where the risk hides.

I can show you the scopes. I can show you the token lifetime. I can show you that your instance is yours. That's trust you can verify, not trust you have to take on faith.

Isolation Is the Price of Being Trusted With a Business

Here's why I can do all of this. I build the systems I use on clients, end to end. I'm not stitching together someone else's tool and hoping their security model is sound. I control how the data is handled at every step, which means I can make isolation, least privilege, and expiring access the defaults instead of the upgrades.

That's a deliberate choice about how I work. I'm a builder, not a slide deck. If you want the longer version of why that matters, I wrote about being the one who builds the systems, not just advises on them.

Isolation by default. Read-only by default. Access that expires by default. This is the baseline I bring before a single line of AI work touches a client's data. The interesting AI systems, the pricing engines, the content pipelines, the automation, all of that comes after the data is handled right. Not before.

So if you're considering bringing someone in to work with your orders, your customers, and your revenue, the first question to ask isn't what AI they'll build. It's how they isolate your data from everyone else's. The answer tells you whether they've earned the right to touch your books.

If they can't answer it plainly, that's your answer.

Ready to bring AI leadership into your company?

I work with a small number of companies at a time. If you're serious about AI, apply to work together and I'll review your application personally.

Apply to Work Together

Get AI insights for business leaders

Practical AI strategy from someone who built the systems — not just studied them. No spam, no fluff.

Ready to automate your growth?

Book a free 30-minute strategy call with Hodgen.AI.

Book a Strategy Call