S3 — Cheat Sheet
Verified against AWS documentation on 2026-10-12 · ⚠️ = changed vs older material: learn the value shown here (older practice material may say otherwise; full list in the guide's "Changed vs older material") · ⚠️ unverified = not confirmed in AWS docs, don't rely on it · explanations and examples: notes/s3-guide.md.
Buckets objects keys and metadata
| Topic | Current facts | Memory hook |
|---|---|---|
| Bucket names | 3–63 chars; lowercase letters, digits, -, .; begin and end with a letter or digit; no ..; not IP-shaped |
Global per partition |
| Reserved name parts ⚠️ | Prefixes xn--, sthree-, amzn-s3-demo-; suffixes -s3alias, --ol-s3, .mrap, --x-s3, --table-s3 |
AWS keeps some names for itself |
| Account regional namespace | <prefix>-<account-id>-<region>-an created with x-amz-bucket-namespace: account-regional; only your account can ever own it |
Your own slice of the namespace |
| Buckets per account ⚠️ | 10,000 by default, raisable to 1,000,000 (older: 100) | |
| Bucket identity | Name and Region fixed at creation; ownership not transferable; a deleted name can be re-created by anyone | Delete = give the name away |
| Object size ⚠️ | 0 B to 50 TB (48.8 TiB); single PutObject ≤ 5 GB; console ≤ 160 GB |
One PUT, five gigs |
| Keys | ≤ 1,024 bytes UTF-8, case-sensitive; "folders" are prefixes split on / |
Flat namespace, painted folders |
| User metadata | x-amz-meta-*, ≤ 2 KB, names stored lowercase, immutable: change with CopyObject + MetadataDirective=REPLACE |
Carved at upload |
| System metadata you set | Content-Type, Cache-Control, Content-Disposition, Content-Encoding, x-amz-storage-class, x-amz-server-side-encryption, x-amz-website-redirect-location |
|
| Object tags | ≤ 10 per object; key ≤ 128, value ≤ 256 chars; mutable; PutObjectTagging replaces the whole set; GetObject returns only x-amz-tagging-count |
Sticky notes you can swap |
| Tag uses | IAM/bucket policy conditions (s3:ExistingObjectTag/<key>), lifecycle and replication filters, Storage Class Analysis |
|
| Metadata search ⚠️ | S3 Metadata tables (Iceberg, query with Athena, GA 2025-01-27) or an own DynamoDB index; LIST filters by prefix only | |
| Consistency | Strong read-after-write for object PUT, DELETE, LIST; bucket configuration eventually consistent | Objects instant, settings settle |
| Conditional writes ⚠️ | If-None-Match: * / If-Match: <ETag> on PutObject, CompleteMultipartUpload, CopyObject (since 2025-10-29) → 412 Precondition Failed; a racing delete gives 409 (If-None-Match) or 404 (If-Match) |
First writer wins |
| Conditional deletes ⚠️ | If-Match: <ETag> on DeleteObject / DeleteObjects since 2025-09-16; enforce with s3:if-match |
|
| 403 vs 404 | Missing key gives 404 NoSuchKey only with s3:ListBucket; without it 403 AccessDenied |
No list, no 404 |
| ETag | MD5 of the data only for single-part, unencrypted or SSE-S3 objects |
Access control Block Public Access and access logs
| Topic | Current facts | Memory hook |
|---|---|---|
| Same-account access | One Allow is enough (identity policy or bucket policy) unless an explicit Deny applies | Either key opens it |
| Cross-account access | Caller's IAM policy and the bucket policy (and the KMS key policy for SSE-KMS) | Both doors must open |
| Bucket policy | ≤ 20 KB; needs Principal; ListBucket on arn:aws:s3:::bucket, object actions on arn:aws:s3:::bucket/* |
Bucket ARN lists, slash-star reads |
| Object Ownership ⚠️ | Default Bucket owner enforced = ACLs disabled for every new bucket since April 2023; other ACLs fail with 400 AccessControlListNotSupported |
ACLs are retired |
| BPA settings | BlockPublicAcls, IgnorePublicAcls, BlockPublicPolicy, RestrictPublicBuckets |
|
| BPA levels ⚠️ | Organization (Organizations S3 policy, all four together), account (s3control, all Regions), bucket, access point (fixed at creation); most restrictive wins |
Strictest layer wins |
| BPA default ⚠️ | All four settings on for every new bucket, whatever the creation method, since April 2023 | |
| "Public" policy | "Principal": "*" without a fixed-value limit such as aws:SourceVpce, aws:PrincipalOrgID or a narrow aws:SourceIp (broader than /8 counts as public) |
|
| Force HTTPS | Deny statement with "Bool": {"aws:SecureTransport": "false"} |
|
| Access logs to S3 | Destination in the same Region and account; SSE-S3 only; no Object Lock, no Requester Pays; grant logging.s3.amazonaws.com s3:PutObject in the bucket policy |
Same Region, same account |
| Log loop | Never log a bucket into itself; each log write creates more logs | |
| Access logs elsewhere ⚠️ | CloudWatch Logs delivery: structured JSON, cross-account and cross-Region, KMS | |
| Log timing | Best effort, usually within a few hours; not a complete accounting |
Encryption at rest and in transit
| Topic | Current facts | Memory hook |
|---|---|---|
| SSE-S3 ⚠️ | Header x-amz-server-side-encryption: AES256; applied to every new upload since 2023-01-05; free; can't be disabled |
Always on |
| SSE-KMS | aws:kms + x-amz-server-side-encryption-aws-kms-key-id; symmetric key in the bucket's Region; CloudTrail logs key use |
Audit trail on the key |
| SSE-KMS permissions | kms:GenerateDataKey to upload, kms:Decrypt to download, both for multipart |
Write = generate, read = decrypt |
aws/s3 key |
Can't be used cross-account; share with a customer managed key | |
| DSSE-KMS ⚠️ | aws:kms:dsse, two AES-256 layers, added 2023-06-13, no S3 Bucket Keys |
Double lock, no shortcut |
| SSE-C | Headers ...-customer-algorithm (AES256), ...-customer-key, ...-customer-key-MD5; HTTPS only; not in console; key needed on every GET/HEAD/copy |
You hold the key, every time |
| SSE-C default ⚠️ | Blocked by default since April 2026; enable with PutBucketEncryption and BlockedEncryptionTypes = NONE; else 403 AccessDenied |
|
| Client-side | Amazon S3 Encryption Client or AWS Encryption SDK; S3 stores ciphertext | |
| Default encryption | SSE-S3, SSE-KMS or DSSE-KMS (never SSE-C); applies to uploads without headers; existing objects unchanged | |
| Re-encrypt old objects ⚠️ | UpdateObjectEncryption turns SSE-S3/SSE-KMS objects into SSE-KMS (new key or Bucket Key) in place, keeping ETag and Last-Modified; unencrypted, SSE-C, DSSE-KMS → CopyObject or Batch Operations Copy (not SSE-C) |
Re-key without a rewrite |
| GET with SSE headers | Sending encryption headers on GET/HEAD of SSE-S3/SSE-KMS/DSSE objects returns 400 Bad Request |
|
| KMS throttling ⚠️ | Shared symmetric quota 10,000/s default, 20,000/s in seven Regions, 100,000/s in us-east-1, us-west-2, eu-west-1 → ThrottlingException |
|
| S3 Bucket Key | Cuts KMS request costs by up to 99 %; new objects only; encryption context becomes the bucket ARN |
Versioning MFA Delete and Object Lock
| Topic | Current facts | Memory hook |
|---|---|---|
| Versioning states | Unversioned → enabled ↔ suspended; never back to unversioned | One-way door |
| Existing objects | Version ID null when versioning is first enabled |
|
| Simple DELETE | Adds a delete marker (GET → 404); delete the marker to restore |
Marker hides, doesn't destroy |
| DELETE with version ID | Permanently removes that version | |
| Suspended bucket | New writes overwrite the null version; older versions are kept |
|
| MFA Delete | MFA needed to suspend versioning and to permanently delete versions; root user only; CLI/API only; incompatible with lifecycle | Root, CLI, no lifecycle |
| Object Lock ⚠️ | Requires versioning; can be enabled on existing buckets (since 2023-11-20); can't be disabled | |
| Governance mode | Bypass with s3:BypassGovernanceRetention + x-amz-bypass-governance-retention: true |
Governance has a back door |
| Compliance mode | Nobody, root included, can delete or shorten; only extend | Compliance has no door |
| Legal hold | On/off, no expiry, s3:PutObjectLegalHold, independent of retention |
Holds until lifted |
| Delete on a locked version | Simple DELETE adds a marker; permanent delete → 403 |
|
| Retention limits | Max 100 years; cap with s3:object-lock-remaining-retention-days; PUT with retention needs Content-MD5 or a checksum header |
Replication CRR and SRR
| Topic | Current facts | Memory hook |
|---|---|---|
| Requirements | Versioning on source and destination; IAM role trusted by s3.amazonaws.com; caller needs iam:PassRole |
Versions both ends |
| What replicates | Objects written after the rule, with metadata, tags, ACL updates, Object Lock retention | New only |
| Existing objects | S3 Batch Replication (also failed and already-replicated objects) | Batch for the backlog |
| Never replicated | Version-ID deletes, lifecycle actions, replicas from another rule, Glacier Flexible/Deep Archive objects, bucket settings | No chains |
| Delete markers | Not by default; enable DeleteMarkerReplication (not with tag-based rules) |
|
| SSE-KMS objects | Opt in with SseKmsEncryptedObjects, set ReplicaKmsKeyID in the destination Region, grant kms:Decrypt + kms:Encrypt |
KMS needs an invitation |
| SSE-C objects ⚠️ | Replicated by default since 2022-10-24 | |
| Cross-account | Destination bucket policy must allow the source role; Bucket owner enforced makes the destination own replicas | |
| RTC ⚠️ | SLA: 99.9 % of objects replicated within 15 minutes (credits below 99.9 %; 99.99 % is the design figure); metrics and threshold events; 1 Gbps default transfer quota; not for Batch Replication | Fifteen-minute promise |
| Limits | 1,000 rules per configuration; 28 destinations per source (adjustable) | |
| Status values | PENDING, COMPLETED, FAILED on the source; REPLICA on the copy |
|
| CRR vs SRR uses | CRR: distant DR or regulator copy, local reads in another Region; SRR: in-country copies, one bucket for many log sources, live prod data in a test account |
Storage classes and lifecycle rules
| Class | AZs · availability · min duration · min billable size | Memory hook |
|---|---|---|
| Standard | ≥ 3 · 99.99 % · none · none | Hot by default |
| Intelligent-Tiering | ≥ 3 · 99.9 % · none · none (< 128 KB not monitored); no retrieval fees | Let S3 decide |
| Standard-IA | ≥ 3 · 99.9 % · 30 days · 128 KB; per-GB retrieval fee | Rare but instant |
| One Zone-IA | 1 · 99.5 % · 30 days · 128 KB; lost if the AZ is destroyed | Re-creatable only |
| Glacier Instant Retrieval | ≥ 3 · 99.9 % · 90 days · 128 KB; milliseconds | Archive price, instant read |
| Glacier Flexible Retrieval | ≥ 3 · 99.99 % after restore · 90 days · 40 KB overhead; restore needed | Minutes to hours |
| Glacier Deep Archive | ≥ 3 · 99.99 % after restore · 180 days · 40 KB overhead; restore needed | Cheapest, slowest |
| Express One Zone ⚠️ | 1 (your choice) · 99.95 % · none · none; directory buckets, single-digit ms | Fastest, one AZ |
| Topic | Current facts | Memory hook |
|---|---|---|
| Durability | 99.999999999 % (11 nines) for all current classes | |
| Flexible Retrieval restores | Expedited 1–5 min, Standard 3–5 h, Bulk 5–12 h (free) | 5 minutes, 5 hours, 12 hours |
| Deep Archive restores | Standard ≤ 12 h, Bulk ≤ 48 h, no Expedited | 12 and 48 |
| Restore mechanics | RestoreObject with Days + Tier; temporary copy billed at Standard; x-amz-restore shows progress; 1,000 restore requests/s |
|
| Intelligent-Tiering tiers ⚠️ | Infrequent after 30 days, Archive Instant after 90; opt-in Archive Access 90–730 days, Deep Archive Access 180–730 days | |
| Lifecycle actions | Transition, Expiration, NoncurrentVersionTransition, NoncurrentVersionExpiration, AbortIncompleteMultipartUpload, ExpiredObjectDeleteMarker |
|
| Lifecycle limits | 1,000 rules per bucket; filters by prefix, tags, size; PUT replaces the whole configuration | Send every rule |
| Small objects ⚠️ | < 128 KB not transitioned to any class by default since September 2024 (older: only IA transitions skipped); override with size filters or varies_by_storage_class |
|
| IA transition age ⚠️ | No minimum age before Standard-IA/One Zone-IA since 2026-07-16: Days 0 or more (older: 30 days in Standard); 30-day storage minimum still billed |
|
| Waterfall | Down only; One Zone-IA → only Glacier Flexible or Deep Archive; Glacier Flexible → only Deep Archive; never back up | Downhill only |
| Versioned expiration | Adds delete markers; also expire noncurrent versions and orphaned markers | Expiring current grows the bucket |
| Lifecycle timing | Rounded to midnight UTC; runs asynchronously; billing changes when the rule is satisfied | |
| Bucket policy vs lifecycle | Even a Deny for every principal doesn't stop lifecycle expirations or transitions; disable the rule |
|
| Storage Class Analysis | Standard → Standard-IA advice only; charts in 24–48 h; result after ~30 days; daily CSV export |
Event notifications and EventBridge
| Topic | Current facts | Memory hook |
|---|---|---|
| Destinations | SNS standard topic, SQS standard queue, Lambda, EventBridge; same Region; one destination per configuration | |
| FIFO | SNS FIFO and SQS FIFO aren't direct destinations; reach SQS FIFO through EventBridge | FIFO via the bus |
| Event types | ObjectCreated:*, ObjectRemoved:*, ObjectRestore:*, Replication:*, LifecycleExpiration:*, LifecycleTransition, IntelligentTiering, ObjectTagging:*, ObjectAcl:Put, ObjectRetention:Put |
|
| Lifecycle deletes | ObjectRemoved:* doesn't fire; use LifecycleExpiration:* |
|
| Filters | Prefix and suffix only, no wildcards, case-sensitive; no overlapping filters for the same event type | |
| Several consumers | One SNS topic fan-out or EventBridge rules | Fan out, don't duplicate |
| Delivery | Normally a few seconds, no guaranteed bound; at least once; duplicates possible; unordered | Idempotent consumers |
sequencer |
Orders events for the same key only (left-pad, then compare) | |
| Event message | Up to 64 KB; key URL-encoded (+ for spaces); s3:TestEvent has no Records |
Decode the key |
| Permissions | Lambda resource policy (lambda:InvokeFunction for s3.amazonaws.com), SNS topic policy (SNS:Publish), SQS queue policy (SQS:SendMessage), scoped by aws:SourceArn + aws:SourceAccount |
Destination says yes |
| Saving a configuration | S3 validates each destination (SNS/SQS test message, Lambda permission check); one failure fails the whole PUT; the call replaces the entire configuration | Destination must say yes first |
| Encrypted SQS/SNS | Key policy must allow s3.amazonaws.com kms:GenerateDataKey + kms:Decrypt |
|
| Recursion | Output into the triggering bucket/prefix re-triggers the function; separate bucket or prefix | |
| EventBridge | "EventBridgeConfiguration": {} sends all events; no extra S3 permissions; filter on any field; ≤ 5 targets per rule; archive and replay |
|
| Notifications quota | 100 notification configurations per bucket |
Performance multipart uploads and Transfer Acceleration
| Topic | Current facts | Memory hook |
|---|---|---|
| Request rate | Per partitioned prefix: 3,500+ writes and 5,500+ reads per second; any number of prefixes | Scale by prefix |
503 Slow Down |
S3 is scaling up; retry with backoff, spread keys over more prefixes | |
| Latency | Roughly 100–200 ms for small objects; cache with CloudFront/ElastiCache or use Express One Zone for less | |
| Multipart sizes | Recommended from 100 MB, required above 5 GB; ≤ 10,000 parts of 5 MiB–5 GiB (last part smaller) | |
| Multipart lifecycle | Parts billed until complete or abort; add AbortIncompleteMultipartUpload |
Finish or abort |
| Multipart permissions | s3:PutObject for create/upload/complete; s3:AbortMultipartUpload, s3:ListMultipartUploadParts separate; SSE-KMS adds kms:GenerateDataKey + kms:Decrypt |
|
| CLI defaults | multipart_threshold 8 MB, multipart_chunksize 8 MB, max_concurrent_requests 10 |
|
| Byte-range GET | Range: bytes=0-1023; parallel downloads, partial reads, cheap retries; partNumber reads one part |
Read just the slice |
| Transfer Acceleration | Edge locations + AWS backbone; <bucket>.s3-accelerate.amazonaws.com; no periods in the name; up to 20 min to take effect |
Long distance only |
| S3 Select ⚠️ | Closed to new customers since 2024-07-25; use byte ranges, Athena or app-side filtering | |
| Large objects > 5 TB | SDK Transfer Manager with the CRT recommended |
Presigned URLs CORS and static websites
| Topic | Current facts | Memory hook |
|---|---|---|
| Presigned URL | Pre-signed request for one operation on one key; uses the creator's permissions; reusable until expiry | Borrowed signature |
| Lifetimes | Console 1 min–12 h; CLI/SDK up to 7 days (604,800 s) with IAM user keys; temporary credentials end it sooner | Seven days, at most |
aws s3 presign |
GET only; --expires-in default 3,600 s |
CLI signs reads |
| Uploads | SDK presigned PUT (send the same Content-Type) or presigned POST with conditions like content-length-range |
|
| Errors | SignatureDoesNotMatch (clock, headers, Region), ExpiredToken (credentials expired), AccessDenied (creator lacks permission or URL expired) |
|
| Restrict presigned use | s3:signatureAge (ms) in a bucket policy; aws:SourceIp / aws:SourceVpce still apply |
|
| CORS preflight | Browser OPTIONS with Origin, Access-Control-Request-Method, Access-Control-Request-Headers; S3 uses the first matching rule |
|
| CORS rule elements | AllowedOrigins, AllowedMethods (GET, PUT, POST, DELETE, HEAD), AllowedHeaders, ExposeHeaders, MaxAgeSeconds; ≤ 100 rules |
|
| Where CORS goes | On the bucket being called, not on the site that served the page | Configure the target |
Read ETag in JavaScript |
List ETag in ExposeHeaders |
|
| Website endpoints | http://<bucket>.s3-website-<region>.amazonaws.com or ...s3-website.<region>...; HTTP only; GET/HEAD only; no access points |
HTTPS = CloudFront (or Amplify Hosting) |
| Public website | BPA allowing public policies + bucket policy s3:GetObject for "*" on bucket/*; index document required |
|
| Website errors | 403 = not publicly readable; 404 = key or index document missing |
|
| Custom domain | Route 53 alias; bucket name must equal the host name |
Access Points and Object Lambda
| Topic | Current facts | Memory hook |
|---|---|---|
| Access point | Named endpoint for one bucket with its own policy, BPA settings and network origin (Internet or VPC) | One door per app |
| Limits | 10,000 per account per Region (adjustable); names 3–50 chars unique per account+Region; policy ≤ 20 KB | |
| Fixed at creation | Bucket, network origin, BPA settings | |
| Two policies | Access point policy and bucket policy must allow; delegate with s3:DataAccessPointAccount |
Bucket delegates, door decides |
| Restrictions | Object operations only; HTTPS + SigV4 only; no anonymous access; not a replication destination | |
| Addressing | ARN arn:aws:s3:<region>:<account>:accesspoint/<name> or the -s3alias alias in place of a bucket name |
|
| VPC origin | Requests only from that VPC through an endpoint whose policy allows both the access point and the bucket | |
| Condition keys | s3:DataAccessPointArn, s3:DataAccessPointAccount, s3:AccessPointNetworkOrigin |
|
| Object Lambda flow | Object Lambda Access Point → Lambda → supporting access point; function calls WriteGetObjectResponse within 60 s (s3-object-lambda:WriteGetObjectResponse) |
No write-back, 500 |
| Object Lambda status ⚠️ | Existing customers and selected APN partners only since 2025-11-07 | |
| Alternatives | Lambda behind a function URL, API Gateway or CloudFront; client-side processing |
Numbers to know
| Item | Value | Note |
|---|---|---|
| Maximum object size | 50 TB (48.8 TiB) ⚠️ | Older material: 5 TB |
Single PutObject |
5 GB | Larger → multipart |
| Console upload | 160 GB | |
| Multipart recommended from | 100 MB | Required above 5 GB |
| Parts per upload | 10,000 | Part numbers 1–10,000 |
| Part size | 5 MiB – 5 GiB | Last part may be smaller |
| Object key length | 1,024 bytes (UTF-8) | Prefix counts |
| User-defined metadata | 2 KB | Within the 8 KB PUT header limit |
| Tags per object | 10 | Key 128, value 256 characters |
| Buckets per account | 10,000 default ⚠️ | Up to 1,000,000; older: 100 |
| Bucket name length | 3–63 characters | |
| Bucket policy size | 20 KB | Same for access point policies |
| Requests per prefix per second | 3,500 writes / 5,500 reads | Unlimited prefixes |
| Small-object latency | ~100–200 ms | First byte for larger objects |
| Versioning settle time | ~15 minutes | Before writing after first enable |
| Lifecycle rules per bucket | 1,000 | Not adjustable |
| Notification configurations per bucket | 100 | |
| Event message size | Up to 64 KB | Set SQS MaximumMessageSize ≥ 64 KB |
| Replication rules / destinations | 1,000 / 28 | Destinations adjustable |
| Replication Time Control | 15 minutes for 99.9 % of objects ⚠️ | SLA level; 1 Gbps default transfer quota |
| Access points per account per Region | 10,000 | Adjustable |
| Access point name length | 3–50 characters | |
| CORS rules per bucket | 100 | |
| Presigned URL maximum (SDK/CLI) | 7 days = 604,800 s | IAM user keys, SigV4 |
| Presigned URL in the console | 1 minute – 12 hours | |
aws s3 presign default |
3,600 s | GET only |
| Glacier Flexible Retrieval restores | 1–5 min / 3–5 h / 5–12 h | Expedited / Standard / Bulk |
| Glacier Deep Archive restores | ≤ 12 h / ≤ 48 h | Standard / Bulk |
| Minimum storage duration | 30 d (IA classes) · 90 d (Glacier IR, Flexible) · 180 d (Deep Archive) | Early deletes billed |
| Minimum billable size | 128 KB (IA classes, Glacier IR) | Archive classes: 40 KB overhead per object |
| Intelligent-Tiering moves | 30 d → Infrequent, 90 d → Archive Instant | Archive tiers up to 730 d ⚠️ |
| Lifecycle default minimum transition size | 128 KB ⚠️ | Since September 2024 |
| Designed availability | 99.99 % Standard · 99.9 % IA, IT, Glacier IR · 99.5 % One Zone-IA · 99.95 % Express One Zone | |
| Durability | 11 nines | All current classes |
| KMS symmetric request quota | 10,000 / 20,000 / 100,000 per second ⚠️ | Default / seven Regions / us-east-1, us-west-2, eu-west-1 |
| Object Lock maximum retention | 100 years | |
| Transfer Acceleration activation | Up to 20 minutes | |
| Storage Class Analysis | 24–48 h to first data · ~30 days to a result | |
| Archive restore request rate | 1,000 per second per account | ThrottlingException above |
| Object Lambda response window | 60 seconds | WriteGetObjectResponse |
Decision rules
- If you see "two writers must not overwrite the same key" with no new service, think
If-None-Match: *(412 on conflict). - If you see "change metadata of existing objects", think
CopyObjectonto itself withREPLACE. - If you see "find objects by tag or metadata", think S3 Metadata tables with Athena or a DynamoDB index fed by events.
- If you see
403for a key that may not exist, think missings3:ListBucket. - If you see cross-account
AccessDeniedalthough the caller's IAM policy allows it, think missing bucket policy (or KMS key policy). - If you see
AccessControlListNotSupported, think ACLs disabled: drop the ACL or sendbucket-owner-full-control. - If you see "no bucket may ever be public", think account- or organization-level Block Public Access.
- If you see "only HTTPS", think a Deny on
aws:SecureTransport=false. - If you see "audit key use" or "control the key policy", think SSE-KMS with a customer managed key.
- If you see "two independent encryption layers", think DSSE-KMS.
- If you see "keys must never be stored in AWS" with server-side encryption, think SSE-C over HTTPS (unblocked with
BlockedEncryptionTypes). - If you see KMS
ThrottlingExceptionon a busy SSE-KMS bucket, think S3 Bucket Keys, then a KMS quota increase. - If you see "re-key existing SSE-S3 objects to SSE-KMS without copying them", think
UpdateObjectEncryption. - If you see "undo an accidental delete", think versioning: delete the delete marker.
- If you see "nobody, not even root, may delete for N years", think Object Lock compliance mode.
- If you see "only special admins may lift protection", think Object Lock governance mode.
- If you see "existing objects didn't replicate", think S3 Batch Replication.
- If you see SSE-KMS objects not replicating, think
SseKmsEncryptedObjects+ReplicaKmsKeyID+ KMS permissions. - If you see "replicate within 15 minutes with an SLA", think Replication Time Control.
- If you see "unknown access pattern", think Intelligent-Tiering.
- If you see "archive with millisecond reads", think Glacier Instant Retrieval.
- If you see "cheapest archive, 12–48 hours is fine", think Glacier Deep Archive.
- If you see a versioned bucket that keeps growing, think
NoncurrentVersionExpiration+ExpiredObjectDeleteMarker. - If you see "abandoned uploads cost money", think
AbortIncompleteMultipartUpload. - If you see two consumers for one S3 event, think SNS fan-out or EventBridge.
- If you see S3 events into an SQS FIFO queue or advanced filters, think EventBridge.
- If you see
503 Slow Down, think more prefixes and retries with backoff. - If you see big uploads across continents, think multipart upload + Transfer Acceleration.
- If you see "temporary upload or download of one private object", think a presigned URL (SDK for PUT).
- If you see a browser preflight failure against S3, think a CORS rule on the bucket being called.
- If you see "one bucket, many teams, policy too large", think access points with a delegating bucket policy.
Memory hooks
- One PUT, five gigs; one object, fifty terabytes.
- Metadata is carved at upload; tags are sticky notes.
- No list, no 404.
- Same account: either key opens it; cross-account: both doors must open.
- Bucket ARN lists, slash-star reads.
- ACLs are retired; policies run the house.
- The strictest Block Public Access layer wins.
- SSE-S3 is always on; KMS leaves footprints; SSE-C means you carry the key every time.
- Write = GenerateDataKey, read = Decrypt.
- A delete marker hides, it doesn't destroy.
- Governance has a back door; compliance has none.
- Versions at both ends, or nothing replicates.
- Replication copies the future; Batch Replication copies the past.
- Replicas never chain.
- Lifecycle only runs downhill.
- Instant archive = Glacier IR; patient archive = Flexible; deepest and slowest = Deep Archive.
- Expiring current versions grows a versioned bucket.
- Events arrive at least once and out of order: build idempotent consumers.
- Decode the key before you GET it.
- Fan out through SNS; filter finely with EventBridge.
- Scale reads by prefix, not by bucket.
- Finish or abort every multipart upload.
- The URL carries the creator's permissions, never more.
- CORS goes on the bucket being called.
- One bucket, many doors: access points.