Skip to content
Rooz Jalali
Go back

Macie and the hard problem of finding PII

Amazon Macie has been generally available since 2017, was rebuilt and relaunched in 2020, and in 2026 still has roughly the same set of complaints attached to it. It only really looks at S3. It misses names and national insurance style identifiers often enough that people open support threads about it. It produces false positives that need tuning away with allow lists. It tells you where sensitive data might be and does nothing about it.

The easy explanation is that AWS has not prioritised it. I think that is a small part of a more interesting answer, and the more interesting answer is worth understanding because it applies to any tool you might replace Macie with.

Table of contents

Open Table of contents

What it does well first

Credit where it is due, because the criticism lands better afterwards.

Macie is genuinely good at high confidence structured identifiers. Card numbers, AWS credentials, private keys and anything else with a checksum or a distinctive shape are found reliably, and finding a live access key in an S3 bucket is worth the subscription on its own.

The bucket inventory and sensitivity scoring are useful even when the detection underneath is imperfect, because most organisations genuinely do not know what is in their object storage. Automated sensitive data discovery, added in 2022, made continuous sampling affordable enough to leave running, which was a real improvement over paying to scan everything.

It also integrates properly. Findings go to Security Hub and EventBridge, the multi account model works through Organizations, and you can retrieve a small number of examples of what triggered a finding without giving anybody standing access to the data.

What it has not fixed

The gaps have been stable long enough to be characterised as design rather than backlog.

Coverage remains S3 shaped. Databases are not supported directly. The documented approach for relational data is to export snapshots to S3 in Parquet and scan those, and for DynamoDB to export the table and scan that. It works, and it is a workaround, with all the staleness and cost that copying data implies.

Detection of the identifiers people actually care about is weak in exactly the cases that matter. Names, addresses and unstructured references are contextual, and Macie leans on nearby keywords to decide. Give it a well labelled CSV and it does fine. Give it a Parquet file whose columns are called c1 through c40, or a free text notes field in an export, and it will frequently find nothing at all.

It is a discovery service and not a control. It does not redact, does not block, does not enforce anything at row or column level. Plenty of teams buy it expecting prevention and get a report.

And the recent release notes tell their own story. The visible additions across 2024 to 2026 were VPC interface endpoint support, monitoring for a larger number of buckets, and new managed identifiers for national identification and taxpayer numbers in Argentina, Chile, Colombia and Mexico. That is useful, unglamorous plumbing and catalogue expansion. It is not work on the core detection problem.

The discrimination problem, concretely

Take the most basic question you can ask a data classifier. Is this string a payment card number, or is it one of your own reference numbers?

Macie decides with some combination of three signals: whether the digits satisfy the Luhn checksum, whether the leading digits fall inside a known issuer range, and whether a relevant keyword appears within about thirty characters of the match.

Consider what that means for a table of support ticket references. Luhn is a modulo ten checksum, so for any fifteen digit prefix exactly one of the ten possible final digits produces a valid number. A tenth of all sixteen digit strings pass it. If your ticket numbers happen to begin with a four, they also sit inside the Visa issuer range. Ten million sequential ticket references therefore contain roughly a million strings that satisfy both tests, and no checksum in existence can separate them from real cards.

Now run it in the other direction. Put ten thousand genuine card numbers in a Parquet column called c12, with no header text and nothing keyword shaped nearby, and the proximity requirement means Macie may report nothing at all.

The same three signals produce both failure directions at once. What would resolve either of them is context, and context is the one thing Macie has no way to accept. You know the column is called ticket_ref. You know its format. You know it is never a card. There is no mechanism to say so.

The tuning that exists, and why it is the wrong shape

Macie is not untunable, to be fair. Two mechanisms exist and both predate 2023.

You can choose which managed data identifiers a job uses, and exclude specific ones. That is identifier level and all or nothing. You can switch card detection off for a job, which is not what anybody wants. You want it on everywhere except one column.

You can write allow lists of text or patterns that should never be reported. Closer, still wrong. Allow lists match on values and patterns with no reference to location, so to suppress ticket references you either enumerate them, impossible for identifiers generated continuously, or write a pattern loose enough that it also suppresses the genuine cards they resemble. An allow list cannot express “in this bucket, in this column”.

What is missing is negative typing scoped to a place. A way to declare that objects under a prefix have a known schema, that a named field carries an internal reference of a stated format, and that it is never a card number whatever Luhn reports. Custom data identifiers only let you add detections. Nothing lets you declare what something is not.

So why has it taken so long

Six reasons, roughly in order of how much I think they matter.

AWS cannot look at your data, which explains less than it appears to

Every machine learning product you can think of improves by studying its failures on real user data. Someone examines what it got wrong, labels it, feeds it back. That loop is why detection systems improve.

AWS has cut that loop deliberately. Customer content in S3 is not theirs to read, and the commercial proposition of the entire platform depends on that being true and being seen to be true. The people improving the detectors cannot examine the documents those detectors failed on.

I initially took this to be most of the explanation. I no longer think so. It accounts for one narrow thing, that supervised tuning against your actual misses is unavailable, and I think it then gets used as cover for the rest.

The failure cases in this area are synthesisable. Nobody needs to see your data to generate ten million sequential sixteen digit references, mix them with the test card numbers the card schemes publish for precisely this purpose, strip the column names, wrap the result in Parquet and a nested archive, and measure what a detector finds. That is an afternoon of work, and it yields a benchmark that could be published, versioned and regressed against on every release. The absence of any such published figure is a choice, not a constraint.

The privacy argument also says nothing about declarative context. Letting a customer describe their own schema requires no access to customer data whatsoever, because the customer volunteers the description. It is the one improvement that is both plainly useful and entirely unblocked by the constraint AWS points at when asked why detection is hard.

So the honest position is narrower than the one I started with. The privacy architecture makes one class of improvement genuinely difficult. The rest of the gap is a decision about where to spend engineering effort.

Nobody knows the false negative rate

You can count findings. You cannot count misses.

Neither AWS nor you knows what proportion of the sensitive data in your buckets Macie failed to identify, because establishing that would require someone to read everything and mark it up by hand, which is the problem you bought the tool to avoid.

This has an unpleasant consequence. A product whose main failure mode is invisible generates very little pressure to improve. False positives annoy people loudly and get addressed, which is why allow lists and tuning exist. False negatives annoy nobody until a breach notification, at which point it is somebody else’s conversation.

Precision and recall pull against each other

The two failure modes are not independent. Loosen the detectors to catch the ambiguous cases and finding volume rises fast, because at the scale object storage reaches, a small percentage of a very large number is an unusable number. Tighten them and you miss things.

Faced with that trade, a platform vendor sensibly optimises for precision. Confident findings look competent and generate few complaints. The cost is silent misses, and silent misses are precisely what a compliance obligation is about. The incentives and the requirement point in opposite directions.

PII is contextual, not a pattern

A nine digit number is a social security number in one column and a part number in the next. Distinguishing them requires understanding the surrounding document, which is why keyword proximity exists in the first place.

That approach inherits a dependency on your data being self describing. Well named columns and sensible headers make it work. Machine generated schemas, opaque column names, compressed archives, images requiring optical character recognition and free text buried in log lines all defeat it, and those describe a large share of real data lakes.

This is not a gap somebody forgot to close. It is the actual difficulty of the problem, and every competitor has the same one.

The identifier catalogue has no end

Personal data is defined differently in every jurisdiction, and the identifiers themselves are country specific. Each new country means understanding its formats, whether they carry a checksum, what keywords appear near them and in which languages.

That March 2025 release adding four Latin American countries is the shape of the work: incremental, unbounded, and never finished. There is no version of Macie that has covered everywhere, and a customer in a country not yet in the catalogue experiences that as the product not working.

The 2020 rebuild reset the clock

Macie today is not an evolution of Macie from 2017. It was re architected and relaunched in 2020 with different internals, much lower pricing and a reduced feature set, losing the user behaviour analytics the original had.

That was probably the right decision, since the original was expensive enough that few people ran it at scale. It also meant starting again, and a detection catalogue is exactly the sort of asset that takes years to accumulate.

What I would actually do

Assuming you are stuck with it, or reasonably choosing it because it is already in the account.

Measure your own recall with planted records. This is the single most useful thing on the list and almost nobody does it. Generate synthetic records that look like your real sensitive data, in your real formats, with your real column naming conventions, and seed them into representative buckets. Then see how many Macie finds. You now have the false negative number that neither AWS nor the console will give you, and you can repeat it after any change.

Fix the naming upstream. Detection depends on context, so context is worth investing in. Columns called customer_email and date_of_birth get found. Columns called c17 do not. This is a data engineering fix that improves every scanning tool you will ever buy, including the one you replace Macie with.

Write custom data identifiers for your own formats. Your internal account references, customer numbers and record identifiers are not in anybody’s managed catalogue and are often the most sensitive things you hold. They are also the easiest to detect, because you control their format.

Treat the output as a lead list, not an inventory. Findings tell you where to look. They are not an authoritative statement of where personal data lives, and presenting them to an auditor as one is a claim you cannot support.

Scan one dirty bucket fully, once. Sampling is what makes continuous discovery affordable, and it is also why it will miss the single misplaced export that actually matters. Pick a bucket you know is bad, pay for the full scan, and compare it against what sampling reported. The difference calibrates how much to trust everything else.

Decide honestly about databases. The export to S3 pattern is legitimate but it copies production data to a second location on a schedule, which is a new risk in exchange for visibility. If the relational estate is where your sensitive data actually lives, this is the point to look at tools built for it rather than bending Macie into the role.

The general lesson

The reason to work through all of this rather than just switching vendors is that most of the causes are not specific to AWS.

Contextual detection is hard everywhere. Nobody can measure recall on data they are not allowed to read. Precision and recall trade against each other regardless of who wrote the classifier. The identifier catalogue is unbounded for every vendor. Any product that promises to have solved this is describing high confidence structured identifiers, which is the easy half, and staying quiet about names in a free text field.

What a competitor can genuinely offer over Macie is scope, because covering databases and other clouds is an engineering decision rather than a hard problem, and enforcement, because redaction and blocking are ordinary features that Macie chose not to have. Those are real reasons to look elsewhere.

Just do not expect the detection underneath to be much better, and do not accept anybody’s claim that it is without planting your own records and counting what comes back.


Share this post:

Previous Post
ISO 42001, ISO 27001 and the AI rulebook
Next Post
Measuring a control you cannot see failing