Secrets Manager stores credentials encrypted with KMS, controls access through IAM, logs every read to CloudTrail, and, the part that justifies its price, rotates supported secrets automatically without anyone touching a config file.\n\nThat last capability is the deciding factor. If you don't need rotation, Parameter Store does the same job for free.\n\n## Creating a secret\n\nbash\naws secretsmanager create-secret \\\n --name prod/payments/db \\\n --description \"Aurora credentials for the payments service\" \\\n --secret-string '{\"username\":\"payments\",\"password\":\"REPLACE_ME\",\"host\":\"db.internal\",\"port\":5432}'\n\n\njson\n{\n \"ARN\": \"arn:aws:secretsmanager:us-east-1:111122223333:secret:prod/payments/db-AbCdEf\",\n \"Name\": \"prod/payments/db\",\n \"VersionId\": \"8f3c1e2a-...\"\n}\n\n\nNote the six random characters AWS appends to the ARN. They're deliberate: they stop a deleted secret's name from being immediately reusable by someone who might inherit its permissions. It also means you can't construct a secret ARN by hand, if you're writing IAM policies, either look the ARN up or end the resource with a wildcard: arn:aws:secretsmanager:us-east-1:111122223333:secret:prod/payments/db-*.\n\nStore JSON rather than a bare string. Rotation functions expect structured fields, and it lets one secret carry the host and port alongside the credentials.\n\nUse a naming convention with a path-like shape, \u003cenv\u003e/\u003cservice\u003e/\u003cpurpose\u003e, because IAM policies can then grant a service everything under its own prefix:\n\njson\n{\n \"Effect\": \"Allow\",\n \"Action\": \"secretsmanager:GetSecretValue\",\n \"Resource\": \"arn:aws:secretsmanager:us-east-1:111122223333:secret:prod/payments/*\"\n}\n\n\n## Reading a secret\n\nbash\naws secretsmanager get-secret-value \\\n --secret-id prod/payments/db \\\n --query SecretString --output text\n\n\nIn application code, retrieve at startup and cache, never call Secrets Manager on every request:\n\n```python\nimport json, boto3\nfrom botocore.exceptions import ClientError\n\n_cache = {}\n\ndef get_secret(name: str, region: str = "us-east-1") -\u003e dict:\n if name in _cache:\n return _cache[name]\n client = boto3.client("secretsmanager", region_name=region)\n try:\n response = client.get_secret_value(SecretId=name)\n except ClientError as err:\n # ResourceNotFoundException here is almost always a region mismatch.\n raise RuntimeError(f"Could not read secret {name}: {err}") from err\n _cache[name] = json.loads(response["SecretString\
Set up an Auto Scaling group with launch templates, ELB vs EC2 health checks and grace periods, then deploy with instance refresh and Spot mixed instances.
Compare target tracking, step, scheduled and predictive scaling, pick the right policy, and use warmup and cooldowns to stop flapping and bad scale-in.
Learn how CloudFront caching works: origin access control for S3, the cache key behind your hit rate, TTL header rules, invalidation costs and error pages.