AWS Builder Center

AWS Secrets Manager: 6 habits that keep secrets out of your codebase

Six practical Secrets Manager habits — rotation, least-privilege IAM, init-time caching, and audit tagging — that keep credentials out of your codebase.

I learned this the hard way. A database password committed to a shared repo, sitting in git history for months while three teams used that same repo. Nobody noticed until a routine log review flagged it. The leak wasn't caused by malice — it was caused by convenience. Secrets end up in codebases because hardcoding them is the fastest way to ship, and "I'll fix it later" never happens. AWS Secrets Manager exists precisely to make the secure path the easy path. Here are six habits I now treat as non-negotiable.
## 1. Use the rotation API instead of copy-pasting credentials
Every time you copy a secret from the console and paste it somewhere, you've created a copy you can't track or revoke. I call the Secrets Manager rotation API (or set up managed rotation) so credentials change on a schedule and the new values are only ever delivered through the API. The moment you reach for copy-paste, you're creating technical debt that shows up in a security review.
## 2. Reference secrets by ARN or name — never values — in code and CI
My rule: a secret's value should never appear in source code, environment files committed to git, or CI/CD pipeline definitions. I reference secrets by their ARN or friendly name (e.g. `prod/orders/db-credentials`) and let the application resolve them at runtime. In CI, the pipeline assumes an IAM role and pulls the secret during the run — the value lives in memory, never on disk or in a build log.
## 3. Enforce least-privilege IAM on secrets with resource policies
Most teams give their application role `secretsmanager:GetSecretValue` on `*` and call it a day. Don't. I attach resource-based policies to individual secrets so only specific roles can read them, and I scope the actions down to exactly what's needed. A reporting Lambda that reads one database credential shouldn't be able to read every secret in the account. When a breach happens, this containment is what keeps a small incident small.
## 4. Set automatic rotation schedules — and actually test them
A static credential is a credential waiting to be stolen. I configure automatic rotation on every secret that supports it, with a 30- or 90-day schedule depending on the workload's sensitivity. The part people skip: testing that the application survives rotation. I've seen rotation break apps that cached connections built on the old password. Test the rotation event end-to-end in a staging environment, including your application's reconnect behavior.
## 5. Fetch secrets at init and cache them — not per request
Calling `GetSecretValue` on every request adds latency, cost, and failure surface. On Lambda, I fetch secrets during the init phase (outside the handler) and reuse them across warm invocations, with a cache TTL that balances freshness against cost. On EC2 or ECS, I load secrets once at startup and refresh on a timer. The one exception: if a secret rotated mid-TTL, my cache handles the "stale secret" case by refreshing on authentication failure — which pairs nicely with habit 4.
## 6. Tag everything and audit with CloudTrail
Secrets Manager charges per secret, so untagged, forgotten secrets quietly inflate your bill. I tag every secret with `Owner`, `Environment`, and `Application` so Cost Explorer allocation reports make sense and cleanup reviews take minutes instead of days. On the audit side, CloudTrail logs every `GetSecretValue` and rotation call — I alert on `GetSecretValue` calls from unexpected roles or regions. Tags manage cost; CloudTrail manages accountability.
## Key takeaways
- Never let a secret value touch your codebase, CI definitions, or git history — reference by ARN or name and resolve at runtime.
- Copy-pasting credentials from the console is a habit to break; use the rotation API and managed rotation instead.
- Scope IAM access to individual secrets with resource policies so one compromised role can't read everything.
- Fetch at init and cache with a TTL, handle stale-secret retries, and tag secrets so Cost Explorer and CloudTrail give you cost and audit visibility.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article