• aws
  • security
  • anti-patterns
  • validation

Common AWS security anti-patterns we validate for

Four AWS security anti-patterns that show up constantly in architecture diagrams — a database in a public subnet, keys instead of roles, plaintext load balancers, and open endpoints — and how to catch each one.

Most AWS security mistakes aren’t exotic. They’re the same handful of anti-patterns, drawn into architecture after architecture, that look completely normal on a canvas. The diagram is valid — the architecture isn’t secure. Here are four we see most often, why each one bites, and how Design Beaver surfaces them: some it flags live as you draw, others it calls out as anti-pattern notes on the service itself.

1. A database in a public subnet

Putting RDS in a public subnet is the one that shows up most, and it’s usually an accident — the database landed in whatever subnet was handy. The problem: a public subnet has a route to an internet gateway. Make the instance publicly accessible on top of that, and leave a security group open, and your database is reachable straight from the internet.

Almost always, nothing outside the VPC needed to reach it in the first place. Per AWS’s own guidance, a publicly accessible RDS instance used only by resources inside the same VPC “unnecessarily exposes the database to the internet when only private connectivity is needed.” The fix is to keep public access off and put the database in a private subnet, reached by security-group rules from the app tier.

Design Beaver flags this one live: draw RDS into a public subnet and it’s marked as a security issue on the spot, not left for a reviewer to catch.

A database in a public subnet is reachable from the internet; the same database in a private subnet is reachable only from the app tier.

2. Long-lived access keys instead of an IAM role

The second one is a credentials habit. An application on EC2 needs to call S3 or DynamoDB, so someone generates an IAM access key, drops it in a config file or environment variable, and moves on. Now there’s a long-lived secret sitting on disk.

Long-lived keys are a standing credential-leak risk — they get committed to git, copied into logs, or left on an instance that outlives the person who made them. An instance profile solves it: attach an IAM role to the instance, and the SDK picks up automatically-rotated temporary credentials from instance metadata. No keys to manage, none to leak.

Design Beaver’s model expects the role, not the keys. Attach an IAM role to the compute node and the access requirement on its connections is satisfied; the anti-pattern is the version with keys on the box.

3. A load balancer serving plain HTTP

A public-facing service behind an ALB with only an HTTP listener — no HTTPS, no certificate — is a quieter one, because everything works. The site loads. Traffic just isn’t encrypted.

That means everything between the client and the load balancer travels in the clear: credentials, session tokens, request and response bodies, all readable by anyone on the network path. The fix is an HTTPS listener on port 443 with an ACM certificate attached, and either drop the HTTP listener or use it only to redirect to HTTPS.

4. A public endpoint with no authorizer

The last one is less clear-cut, and worth being precise about: an API Gateway endpoint with nothing checking who’s calling it. Sometimes that’s exactly right — plenty of APIs are meant to be public. The mistake is doing it by accident, and finding out later that an endpoint you assumed was protected never was.

If the endpoint should require auth, the piece that’s missing is an authorizer. Wire a Cognito user pool to the API as an authorizer and API Gateway validates the token before a request ever reaches your backend. Just as important, the frontend has to actually sign in against that user pool to get a token — an authorizer with nothing authenticating to it is a lock with no key.

Design Beaver treats this one as a nudge, not an alarm — because a public API is a legitimate choice. Draw an API with no authorizer and it points out that the endpoint is public, so it’s a decision you made on purpose rather than one you discover in an audit.

The pattern behind the anti-patterns

Every one of these looks fine on a blank canvas, because a blank canvas has no opinion about security. A line from the internet to a database is the same line as any other. The whole point of validating as you draw is that the tool does have an opinion — it knows a database in a public subnet is exposed, that keys on a box are a liability, that a plaintext listener leaks, and that an unprotected endpoint should at least be a deliberate choice.

None of these are advanced. They’re the ordinary mistakes that make it to production because the diagram never objected. If you’d rather catch them while you’re still drawing, open Design Beaver — it’s live in beta, free, no account required.

Milin Paul

@milinpaul

Lead Software Engineer at EverestEngineering. I write about practical AI systems, engineering architecture, and what actually works in production.

Try Design Beaver on your own architecture

It’s live in beta — free, in your browser, no account required.

Open the app →

Prefer email? Get new features in your inbox:

← Back to all posts