What you'll learn
PutObjectuploads a whole object (up to 5 GiB) and replaces anything already stored under that key.- Set
ContentTypeon every upload, and use user metadata for small facts about the object. - S3 is strongly consistent: once a write succeeds, every read and listing sees it.
Section 01
Uploading with PutObject
PutObjectCommand takes the bucket, the key and a Body — a string, a Buffer, a Uint8Array or a stream. A single PUT can upload up to 5 GiB; above that (and usually above 100 MB) you use multipart upload, which is Quest 8.
If an object already exists under the key, the PUT replaces it. There's no “insert only” by default — Quest 6 shows how to ask for one.
import { PutObjectCommand } from "@aws-sdk/client-s3";
const card = { number: 252, name: "Treecko", types: ["grass"], region: "Hoenn" };
const { ETag } = await client.send(
new PutObjectCommand({
Bucket: "hoenn-pokedex-media",
Key: "cards/0252-treecko.json",
Body: JSON.stringify(card),
ContentType: "application/json",
Metadata: { generation: "3" },
})
);Section 02
Content type and metadata
S3 doesn't guess types from file names. Without ContentType the object is served as binary/octet-stream, so a browser downloads your card instead of displaying it and CloudFront can't compress it.
User metadata is a set of string key–value pairs sent as x-amz-meta-* headers. It comes back with every GET and HEAD, so tools can read the generation without downloading the card. Keep it small (2 KB in total), use lowercase keys, and remember you can't search by it — it's not an index.
| Field | Use it for |
|---|---|
ContentType | How clients should interpret the bytes |
CacheControl | How long browsers and CDNs may cache it |
Metadata | Small, string-only facts about the object |
Tagging | Labels for lifecycle rules, access control and cost reports (up to 10 per object) |
Section 03
What comes back
A successful PUT returns an ETag, a fingerprint of the object. For a single-part upload without SSE-KMS it's the MD5 of the body; for multipart uploads it isn't, so treat it as an opaque version marker, not a checksum. Recent AWS SDKs also add a CRC32 checksum to uploads by default, and S3 verifies it.
New objects are encrypted at rest with SSE-S3 automatically (you'll see ServerSideEncryption: "AES256"). And since December 2020 S3 has been strongly consistent: after the PUT succeeds, any GET, HEAD or LIST sees the new object — no waiting, no stale reads.
Practice
Your turn
Upload Treecko's Pokédex card to cards/0252-treecko.json. Tell S3 it's JSON with ContentType, and tag it with user metadata generation: "3" so tools can read the generation without downloading the card.
ContentType: "application/json" and Metadata: { generation: "3" }.Check
Check your understanding
Quick Quiz · one question, as many tries as you need.
cards/0252-treecko.json and immediately list cards/ from another Lambda function. What does the listing show?Choose one answer.