A business owner showed me, quite proudly, the AI assistant his team had set up. They'd connected it to the company database โ read-only, he stressed, twice โ and now anyone in the office could type a question and get an answer. Who are our top ten customers this quarter? Which sales rep is slipping? It answered in seconds, with names, totals, and a neat little chart.
It was genuinely impressive. It was also every customer, every price, and every margin in his company, sent to a server he has never seen, run by a company he has never spoken to, under terms nobody in that office had read.
I use AI every day, and I'll happily use it on client data. I just don't send it the data. I send it the shape of the data, with IDs where the names used to be, and I put the names back myself.
Read-only is not private
"Read-only" answers the wrong question. It guarantees the AI can't change your data. It says nothing about who gets to see it.
Every time that assistant answers a question, the query result leaves the building. It goes to the AI provider, possibly into their logs, possibly through whatever plugin or connector someone installed to make the integration work. Each of those is a place your data now lives, and each one can be misconfigured, breached, or quietly retained longer than you'd expect. None of it is under your control.
Read-only access prevents damage. It does nothing to prevent disclosure.
And it doesn't matter whether the data is "confidential." A customer list with purchase history is exactly what a competitor would pay for. I wrote about how easily large Lebanese databases have been breached โ you don't want to add an AI pipeline to the list of doors.
The fix is not to stop using AI, and it's not to buy an $18,000 server for your office either. The fix is to stop sending things the AI doesn't need.
What the AI actually needs
Think of the AI as a very smart consultant you met yesterday. You'd show him how your spreadsheet is organised. You would not hand him your client list.
Revenue per customer per month is a calculation. The calculation is identical whether the customer is called Khoury Trading or 7f3a9c2e. The AI needs the structure and the numbers. It doesn't need the names, and it certainly doesn't need to know which company it's working for.
Level one: send the metadata, not the rows
For most reports, the AI never needs to see a single row. Give it the metadata โ the tables, the columns, their types, how they relate โ and ask it to write the query or the analysis code. You run that code on your own server, against your own database. The AI designed the report. It never saw the data.
This covers more than people expect. Monthly sales summaries, slow-moving stock, collection delays per rep โ all of it is logic, and logic only needs the structure.
Level two: send rows with IDs instead of names
Sometimes the AI does need to look at real numbers โ to spot a trend, explain an anomaly, write a summary. Then you send rows, but every name is replaced with an ID before it leaves:
| Field | In your database | What the AI receives |
|---|---|---|
| Customer | Khoury Trading SARL | 7f3a9c2e-41b8-4d0a-โฆ |
| Product | Paracetamol 500mg, box of 24 | c91d04e7-2a6f-49b3-โฆ |
| Sales rep | Rami | 2b6e8f10-9c47-4e15-โฆ |
| Amount | 4,250.00 | 4,250.00 |
The AI comes back with "customer 7f3a9c2e dropped 40% in Q3, mostly on product c91d04e7." Your program swaps the IDs back to names before anyone reads it. The mapping between IDs and real names never leaves your server.
That's the whole trick. To the AI, your best customer is a string of random characters. It does the analysis perfectly well โ it just won't be sending them a Christmas card.
Why GUIDs and not 1, 2, 3
The obvious shortcut is to use your existing database IDs. Customer 1, customer 2, customer 4,812. Don't.
Sequential numbers carry information. Customer 4,812 tells anyone reading that you have roughly five thousand customers. Invoice 10,233 in March and 11,480 in April tells them your monthly volume. The numbers themselves become a description of your business.
A GUID โ a random 128-bit identifier like 7f3a9c2e-41b8-4d0a-โฆ โ says precisely nothing. There's no order, no count, no pattern to read. If you want to be more careful still, generate fresh GUIDs for each export, so nothing can be linked across sessions even if several of them leak.
Where IDs aren't enough
Swapping names for IDs removes the obvious leaks. It doesn't remove all of them, and pretending otherwise would be the kind of security theatre I'm complaining about.
pharma_license_no tells the AI your industry before it reads a single row; rename to something generic when it matters. The outliers. If one customer is 60% of your revenue, anyone who knows your market knows who that is โ no name required. For numbers that sensitive, send totals or ranges instead of rows.
None of this weakens the position. The goal isn't perfect anonymity. The goal is that if everything you ever sent to an AI leaked tomorrow, what leaked is a spreadsheet of random strings and numbers nobody can attach to a name. Compare that to a live connection to your entire database and there isn't a contest.
How we build it
When a client wants AI-generated reports, this is the setup we put in place. It's a small piece of software โ days of work, not months:
- A mapping table on your side. Every customer, product, and rep gets a GUID. It lives in your database and is never exported.
- One export path to the AI. A single layer that picks the columns, swaps names for GUIDs, and drops free text. Nobody pastes raw exports into a chat window, because there's no need to.
- The AI works on structure and IDs. It writes the queries, runs the analysis, drafts the summary.
- Re-mapping on the way back. GUIDs in the AI's output are replaced with real names before a human reads it. Your team sees "Khoury Trading dropped 40%," exactly as if the AI had known all along.
The honest cost is a little friction. Nobody gets to open a chatbot and casually type "how is Khoury doing?" โ the question goes through the system, and the system does the translating. That's a small price for your customer list staying yours.