<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Maximilian Pöhls | Mostly AWS. Small detours.</title><description>Notes and articles on AWS, cloud architecture, and AI.</description><link>https://maximilianpoehls.de/</link><language>en</language><image><url>https://maximilianpoehls.de/_astro/mark.CAXQohDY_26Ephj.png</url><title>Maximilian Pöhls</title><link>https://maximilianpoehls.de/</link></image><item><title>Asking Someone to Be Your Valentine, the Overengineered Way</title><link>https://maximilianpoehls.de/blog/ask-your-valentine-engineer/</link><guid isPermaLink="true">https://maximilianpoehls.de/blog/ask-your-valentine-engineer/</guid><description>A small, silly, delightful weekend project: building an interactive &apos;will you be my Valentine&apos; website instead of just texting the question.</description><pubDate>Thu, 12 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;img src=&quot;https://maximilianpoehls.de/_astro/ask-your-valentine-engineer-cover.CgN1mLos_ZmA41S.webp&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;&lt;p&gt;Not every project needs a business case. Sometimes you just want to ask someone a question, and instead of sending a text, you build a tiny website for it. That’s exactly what &lt;a href=&quot;https://github.com/maxpoe/valentine-fun&quot;&gt;valentine-fun&lt;/a&gt; is. A small, interactive “will you be my Valentine?” page, built mostly because it was more fun than it had any right to be.&lt;/p&gt;
&lt;h2 id=&quot;the-idea&quot;&gt;The idea&lt;/h2&gt;
&lt;p&gt;The premise is simple: a single page that asks the question, with a “yes” and a slightly-too-elusive “no” button that dodges the cursor, some AI-generated cat (or dog) illustrations, and just enough polish to feel like a real, deliberate gift rather than a rushed weekend hack, even though it absolutely was a rushed weekend hack.&lt;/p&gt;
&lt;p&gt;I kept the stack as light as it could possibly be: &lt;strong&gt;Vite&lt;/strong&gt; for the dev server and bundling, &lt;strong&gt;vanilla JavaScript&lt;/strong&gt; for the interaction logic, and plain &lt;strong&gt;CSS3&lt;/strong&gt; for the gradients and animations. No framework, no state management library, no build complexity beyond what Vite gives you for free. For a page that exists to be looked at once and then forgotten, reaching for React would have been like renting a moving truck to bring home a bouquet of flowers.&lt;/p&gt;
&lt;h2 id=&quot;making-it-personal-without-rebuilding-it&quot;&gt;Making it personal without rebuilding it&lt;/h2&gt;
&lt;p&gt;The part I actually enjoyed designing was the customization. Rather than hardcoding a name or hunting through source files every time I wanted to reuse this for someone else, everything personal is driven by environment variables:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;services&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;  valentine-fun&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    image&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;ghcr.io/maxpoe/valentine-fun:latest&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    ports&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;8080:80&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    environment&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;VALENTINE_NAME=Partner&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;VALENTINE_PET=dog&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#85E89D&quot;&gt;    restart&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;always&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Change &lt;code&gt;VALENTINE_NAME&lt;/code&gt; and the question addresses whoever you’re asking. Flip &lt;code&gt;VALENTINE_PET&lt;/code&gt; from &lt;code&gt;cat&lt;/code&gt; to &lt;code&gt;dog&lt;/code&gt; and the whole illustrated theme swaps along with it. That’s the whole configuration surface — two variables, and the entire personality of the site changes. It’s a small thing, but it meant the project stopped being “a page I built once” and became “a page I can hand to a friend for their own Valentine.”&lt;/p&gt;
&lt;h2 id=&quot;shipping-it-like-it-mattered&quot;&gt;Shipping it like it mattered&lt;/h2&gt;
&lt;p&gt;Here’s where the overengineering crept back in: I still built and pushed a proper container image to GitHub Container Registry, with a Dockerfile and an entrypoint script that injects those environment variables into the static build at container start. Realistically, this project could have lived as a single HTML file emailed as an attachment. Instead it has a &lt;code&gt;docker-compose.yml&lt;/code&gt;, a slim Nginx-based image, and a GitHub Actions workflow that builds and publishes it automatically.&lt;/p&gt;
&lt;p&gt;Was that necessary for a page that gets visited once, hopefully says yes, and is never opened again? No. Was it satisfying to &lt;code&gt;docker compose up&lt;/code&gt; a Valentine’s proposal like it was a production microservice? Also no — but I did it anyway, and that’s kind of the point of side projects like this one.&lt;/p&gt;
&lt;h2 id=&quot;why-bother-with-a-real-project-for-something-this-small&quot;&gt;Why bother with a “real” project for something this small&lt;/h2&gt;
&lt;p&gt;Partly because it’s genuinely fun to apply the same discipline — clean structure, reproducible builds, sensible defaults — to something with zero stakes. And partly because these tiny projects are where I actually try new things without worrying about breaking anything important. Vite’s dev experience, a from-scratch CSS animation, a minimal Docker entrypoint pattern — none of it was new to me individually, but stitching it together for something this small and low-pressure is a nice way to keep the muscles warm between “real” work.&lt;/p&gt;
&lt;p&gt;If you want to steal the idea for your own Valentine (or just want a lightweight interactive-page template to fork), the repo is right &lt;a href=&quot;https://github.com/maxpoe/valentine-fun&quot;&gt;here&lt;/a&gt; — clone it, swap in your own name and pet theme, and you’ve got a proposal that took a weekend and somehow also has a Docker image.&lt;/p&gt;
</content:encoded><category>personal</category><category>web</category></item><item><title>Hello World. Again.</title><link>https://maximilianpoehls.de/blog/hello-world/</link><guid isPermaLink="true">https://maximilianpoehls.de/blog/hello-world/</guid><description>The first post on this blog — why I&apos;m writing about my IT journey, AWS, and everything in between. Story so far.</description><pubDate>Thu, 05 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;img src=&quot;https://maximilianpoehls.de/_astro/hello-world-cover.D5eEsuPh_1od1T2.webp&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;&lt;p&gt;This is the first post on this blog. More to come soon — mostly AWS, cloud architecture, and notes from my IT journey.&lt;/p&gt;
&lt;p&gt;I have gone through multiple iterations and blogs over the last decade. This is my newest update I will publish to from now on.&lt;/p&gt;
</content:encoded><category>meta</category></item><item><title>Finding Needles in Haystacks: A Hands-On Look at AWS Macie</title><link>https://maximilianpoehls.de/blog/aws-macie-hands-on/</link><guid isPermaLink="true">https://maximilianpoehls.de/blog/aws-macie-hands-on/</guid><description>Why I built a Demo for AWS Macie, what it&apos;s actually good at, and where its limits show up in the real world.</description><pubDate>Mon, 28 Oct 2024 00:00:00 GMT</pubDate><content:encoded>&lt;img src=&quot;https://maximilianpoehls.de/_astro/aws-macie-hands-on-cover.DVpa3OTT_jG5iO.webp&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;&lt;p&gt;If you’ve ever inherited an AWS account with a dozen S3 buckets, no data inventory, and a vague feeling that &lt;em&gt;something&lt;/em&gt; sensitive is probably sitting in there unencrypted, this post is for you. That’s the exact itch that got me building a small hands-on demo for &lt;a href=&quot;https://github.com/maxpoe/aws-macie-demo&quot;&gt;AWS Macie&lt;/a&gt;. Here’s what I learned along the way, including where Macie earns its keep and where you’ll run into its edges.&lt;/p&gt;
&lt;h2 id=&quot;the-problem-macie-is-solving&quot;&gt;The problem Macie is solving&lt;/h2&gt;
&lt;p&gt;Data sprawl in S3 creeps up on you. Someone spins up a bucket for a proof of concept, drops a CSV export in there “just for now,” and six months later nobody remembers what’s inside or who’s allowed to see it. Auditing that manually at scale is a losing game. You need something that can actually read the objects and tell you what it found.&lt;/p&gt;
&lt;p&gt;That’s the job Macie does. It’s a managed data security service that combines machine learning and pattern matching to scan S3 objects, classify what’s sensitive (PII, credentials, financial data, intellectual property), and surface two kinds of findings: &lt;strong&gt;data findings&lt;/strong&gt; (something sensitive was found) and &lt;strong&gt;policy findings&lt;/strong&gt; (the bucket itself is misconfigured, e.g. public access or no encryption).&lt;/p&gt;
&lt;h2 id=&quot;why-i-built-a-demo-instead-of-just-reading-the-docs&quot;&gt;Why I built a demo instead of just reading the docs&lt;/h2&gt;
&lt;p&gt;I learn infrastructure services by wiring them up and breaking them, not by staring at console screenshots in someone else’s blog post. So the &lt;a href=&quot;https://github.com/maxpoe/aws-macie-demo&quot;&gt;aws-macie-demo&lt;/a&gt; repo is a small, self-contained Terraform stack that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Enables Macie on the account&lt;/li&gt;
&lt;li&gt;Provisions a “sensitive” S3 bucket seeded with sample data, plus a dedicated results bucket&lt;/li&gt;
&lt;li&gt;Sets up a recurring classification job and a custom data identifier&lt;/li&gt;
&lt;li&gt;Wires findings through EventBridge, Lambda, and SNS so you get an actual email when something is found, instead of babysitting the console&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s all reproducible with &lt;code&gt;terraform apply&lt;/code&gt;, which matters if you want to tear it down and rebuild it a few times while you’re poking around, rather than clicking through the console and forgetting what you changed an hour later.&lt;/p&gt;
&lt;h2 id=&quot;walking-through-the-architecture&quot;&gt;Walking through the architecture&lt;/h2&gt;
&lt;p&gt;The demo has the pieces you’d expect from a real Macie rollout, just scaled down to something you can spin up in an afternoon.&lt;/p&gt;
&lt;p&gt;Enabling Macie itself is almost anticlimactic. It’s a single resource:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hcl&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;resource&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; &quot;aws_macie2_account&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; &quot;macie&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  status&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;                       =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;ENABLED&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  finding_publishing_frequency&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;FIFTEEN_MINUTES&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The more interesting part is the classification job, which tells Macie what to scan and how often:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hcl&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;resource&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; &quot;aws_macie2_classification_job&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; &quot;demo-job&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  job_type&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;SCHEDULED&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;     =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;macie-demo-recurring-job-&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;random_id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;demo_unique-id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;hex&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  s3_job_definition&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;    bucket_definitions&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      account_id&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; data&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;aws_caller_identity&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;current&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;account_id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;      buckets&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;    =&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; [aws_s3_bucket&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;macie_demo-bucket-sensitive&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;id]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;  schedule_frequency&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;    daily_schedule&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then there’s a custom data identifier, which is where Macie stops being a black box and starts being your tool. You write a regex for whatever organization-specific pattern you care about — internal employee IDs, a proprietary document header, a project code name:&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;hcl&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;resource&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; &quot;aws_macie2_custom_data_identifier&quot;&lt;/span&gt;&lt;span style=&quot;color:#79B8FF&quot;&gt; &quot;macie_custom_data_identifier&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;        =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;internal-project-code&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  regex&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;       =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;PRJ-[0-9]{6}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;  description&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;Flags internal project reference codes in documents&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From there, findings flow into an EventBridge rule, which triggers a Lambda function, which publishes a formatted notification to an SNS topic that emails a subscriber. It’s a small pipeline, but it’s the same shape you’d use in production, minus the extra accounts, delegated admin setup, and cross-account KMS policies a real org-wide rollout would need.&lt;/p&gt;
&lt;h2 id=&quot;what-impressed-me&quot;&gt;What impressed me&lt;/h2&gt;
&lt;p&gt;The signal-to-noise ratio on the managed identifiers was better than I expected. I seeded the sensitive bucket with sample PII, financial-looking data, and credential-shaped strings, and Macie bucketed all of it correctly without any tuning from me. For the common cases — credit card numbers, SSNs, AWS keys — the out-of-the-box managed data identifiers just work.&lt;/p&gt;
&lt;p&gt;Custom data identifiers close the gap fast, too. Writing the regex-based identifier above took maybe five minutes and it immediately started catching organization-specific patterns that no managed identifier would ever know about. If your sensitive data isn’t a type of PII but a shape specific to your business — an internal case number, a proprietary key format — this is where Macie stops being generic.&lt;/p&gt;
&lt;p&gt;And the EventBridge integration is what makes it operationally real rather than a dashboard nobody checks. Piping findings through EventBridge into Lambda and SNS (or, in a real setup, into Security Hub, Slack, or a ticketing system) is the difference between “Macie found something” and someone on the security team getting paged.&lt;/p&gt;
&lt;h2 id=&quot;where-the-limits-show-up&quot;&gt;Where the limits show up&lt;/h2&gt;
&lt;p&gt;No tool review is complete without the rough edges, so here’s where Macie made me pause.&lt;/p&gt;
&lt;p&gt;It’s S3-only. Macie inspects objects in Amazon S3 and has no visibility into RDS, DynamoDB, EBS snapshots, or anything outside that bucket boundary. If your sensitive data lives in a database, you need a different tool for that layer — Macie isn’t a data-discovery platform for your whole estate.&lt;/p&gt;
&lt;p&gt;Cost scales with data volume, not with findings. Classification jobs are priced per gigabyte scanned, plus a smaller per-object fee for sensitive data discovery, so pointing a recurring job at a multi-terabyte bucket “just to be safe” gets expensive fast. Scope jobs to the buckets that actually warrant regular scanning instead of turning it loose on everything.&lt;/p&gt;
&lt;p&gt;Findings aren’t automatically actioned. Macie tells you what it found and where — it doesn’t quarantine the object, revoke access, or redact anything on its own. You have to build that remediation layer yourself, which is exactly what the EventBridge → Lambda pipeline in this demo stands in for.&lt;/p&gt;
&lt;p&gt;Regex-based custom identifiers can misfire. Proximity rules and keyword hints help, but a poorly scoped regex will either drown you in false positives or miss the pattern entirely. Expect to iterate on custom identifiers the same way you’d iterate on any detection rule.&lt;/p&gt;
&lt;p&gt;And it’s a detective control, not a preventive one. Macie tells you sensitive data landed somewhere it shouldn’t have, after the fact — it doesn’t stop the upload. Pair it with preventive controls like bucket policies, SCPs, and access points rather than treating it as your only line of defense.&lt;/p&gt;
&lt;h2 id=&quot;who-should-actually-use-this&quot;&gt;Who should actually use this&lt;/h2&gt;
&lt;p&gt;If you’re running a handful of S3 buckets with a rough idea of what’s in them, Macie’s managed identifiers alone will tell you something useful on the first scan. If you’re in a regulated space (healthcare, finance, anything brushing up against GDPR, HIPAA, or CCPA), the combination of automated discovery, Security Hub integration, and audit-friendly findings makes a real case for baking Macie into your standard account setup instead of treating it as an afterthought.&lt;/p&gt;
&lt;p&gt;If your sensitive data doesn’t live in S3, or you need continuous real-time blocking instead of periodic discovery, Macie is the wrong tool for that specific job, though it can still be a solid piece of a broader data security posture.&lt;/p&gt;
&lt;h2 id=&quot;try-it-yourself&quot;&gt;Try it yourself&lt;/h2&gt;
&lt;p&gt;The full Terraform stack, including the EventBridge/Lambda/SNS findings pipeline, is in the &lt;a href=&quot;https://github.com/maxpoe/aws-macie-demo&quot;&gt;aws-macie-demo&lt;/a&gt; repo. Clone it, drop in your own &lt;code&gt;variables.tfvars&lt;/code&gt;, and &lt;code&gt;terraform apply&lt;/code&gt; — you’ll have findings landing in your inbox within a day.&lt;/p&gt;
&lt;p&gt;If you end up writing custom data identifiers for a real workload, let me know what patterns you’re matching against. That’s usually where the interesting edge cases live.&lt;/p&gt;
&lt;h2 id=&quot;update-december-2025&quot;&gt;Update (December 2025)&lt;/h2&gt;
&lt;p&gt;A few things have changed since this post first went up in October 2024:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;December 2024&lt;/strong&gt; — Macie added preventative control monitoring, covering up to 10,000 S3 general purpose buckets per account. That nuances the “detective, not preventive” point above a bit: Macie can now continuously monitor your bucket security posture (public access, encryption, policies) instead of only surfacing findings after a scan runs. It’s still not blocking uploads in real time, so pairing it with bucket policies and SCPs still matters.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;March 2025&lt;/strong&gt; — The managed data identifier library grew to cover more region-specific PII, including national ID numbers, taxpayer IDs, and SUBE card numbers for Argentina, Chile, Colombia, and Mexico. Worth checking the current list if you assumed it was US/EU-only.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;July 2025&lt;/strong&gt; — Macie now supports VPC interface endpoints and endpoint policies across all its available regions, so you can keep API traffic inside your VPC instead of routing over the public internet. Handy if your account runs with restrictive egress policies.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Everything else — the S3-only scope, the per-bucket-and-per-GB pricing model, and the Terraform stack in the demo repo — still holds up.&lt;/p&gt;
</content:encoded><category>aws</category><category>security</category></item></channel></rss>