The sidecar I didn't build
A file upload endpoint looks simple until you write down what can arrive through it. On a healthcare-adjacent platform the list is longer than usual: malware, obviously, but also explicit content, and at the far end, material you are legally required to preserve and report. The RFC I inherited had a sensible first answer: a ClamAV sidecar in ECS for scanning, Rekognition for image moderation, and a retention policy to be decided later.
It also had five open questions, and I didn’t know the answers to any of them. So before touching the design I spent the time on primary sources: the federal statute, AWS’s own docs on the services involved, and the pricing pages, which tell you more about a product’s intended use than the marketing does.
Managed scanning won on memory, not just money
ClamAV in a sidecar means your worker holds the file, streams it to the daemon, waits, and then decides. For files up to 50 MB with a safety margin, the task needs about 8 GB of memory to avoid getting killed mid-scan. That’s the number that decided it.
GuardDuty Malware Protection for S3 scans the object where it lands. Results arrive as object tags and EventBridge events; your worker never touches the bytes until they’re clean. The same job fits in 2 GB, and the monthly cost went from roughly $70–100 for a scanning service that someone also has to patch and monitor to about $7 with nothing to operate.
One implementation detail that bit us in review: gate downstream processing on THREATS_FOUND, not on “anything that isn’t NO_THREATS_FOUND.” GuardDuty also returns UNSUPPORTED for file types it can’t scan, and the second condition quietly blocks all of them.
Moderation is where medical imagery breaks the defaults
Rekognition’s moderation labels are tuned for social platforms. Point them at a wound photo, a dermatology image or a post-surgery record and they light up: skin, nudity, gore. Its MinConfidence parameter is global, so you can’t say “be strict about one category and lenient about another” at the API level. You do that in your own code, with per-category thresholds, and you route the ambiguous middle to a human review queue rather than auto-rejecting a legitimate medical document. PDFs need image extraction before any of this applies.
Google Cloud Vision’s SafeSearch handles this class of content noticeably better. We didn’t adopt it in v1 because it would mean a second cloud and a second business associate agreement, but it’s on the list, and I’d evaluate it earlier next time.
Quarantine is two policies, not one
Flagged files are not one category. A virus-positive upload is useful for 30–90 days for forensics and then should be deleted. Suspected illegal content is the opposite: federal law requires preservation, and deletion is the crime. So the quarantine bucket uses S3 Object Lock, and the two kinds of holds have different retention rules and different access paths.
Two more things that don’t appear on the architecture diagram. First, the metadata about a flagged file — who uploaded it, when, from where, what was found — must outlive the file itself. Second, the reporting obligation is a documented manual process with named roles, not a proactive scanner. Preparation is the requirement; automation is optional and, done badly, harmful.
What it cost
At low volume the whole addition runs about $3.43 a month, almost entirely the fixed fee for the KMS customer-managed key. Everything else is usage-based and near zero until it isn’t.
The one thing I’d flag for anyone doing this in CDK: check the removal policy on that KMS key. RemovalPolicy.DESTROY on a key that encrypts medical records is a footgun you will only fire once.
The lesson
Managed services aren’t just cheaper; they remove an entire class of operational work. But the pipeline still has to be designed around the failure paths — unsupported files, false positives on legitimate images, files you’re not allowed to delete. The scanner was the easy part. The policy around what the scanner finds is the actual system.