Verbs With Consequences
You’re building a to-do app. You write an endpoint that deletes a task. You test it by opening the URL in your browser — it works. You close the tab and forget about it.
Three weeks later, tasks start vanishing. Nobody clicked delete. So what deleted them?
Something followed that URL. A crawler indexing your site. A link-preview bot unfurling a shared link. A browser prefetching links so the next page feels faster. All of them treat a URL as safe to fetch whenever they like — because the entire web is built on the assumption that fetching a URL is a read, not a write. You handed them a URL that deletes data.
This is a real class of bug, it has destroyed real data, and it happens for one reason: the developer didn’t understand HTTP methods — specifically, the difference between asking for something and doing something.
Methods look simple. There are eight of them. But which one you use changes everything: how caches behave, how browsers behave, how crawlers behave, and whether your app accidentally destroys data while nobody is watching.
Verbs, not nouns
An HTTP request is a sentence. The URL is the noun — what you’re talking about. The method is the verb — what you want to do with it.
GET /tasks/42
└──┬─┘ └───┬───┘
method noun
"Give me task 42"
DELETE /tasks/42
└──┬───┘ └───┬───┘
method noun
"Delete task 42"
Same noun. Different verb. Completely different outcome. That’s the whole idea.
HTTP method — A token in the request line of an HTTP request that indicates the desired action to be performed on the target resource.
In plain terms: “What I want you to do with this thing.”
The method exists because a URL alone can’t tell a server your intention. POST /tasks and DELETE /tasks point at the same noun; only the verb says whether you’re adding or destroying.
Think of a market stall. The noun is what you’re pointing at — tomatoes. The verb is what you want — show me, give me, how much for. Same goods, different intentions.
But here’s where the market analogy wears out: at a market, the trader can read your tone and your face. She knows whether you’re asking or demanding. HTTP has no face. The verb is the only signal the server gets about intention. Which is why the standards around methods are strict — there’s nothing else for the server to go on.
GET — read
GET asks for a resource. It’s the verb your browser uses every time you type a URL. It’s the verb every link uses. It’s the verb behind far more traffic than every other method combined.
GET /api/tasks → list all tasks
GET /api/tasks/42 → get task #42
GET /api/users/ada → get user "ada"
GET — An HTTP method that requests a representation of the specified resource. Safe and idempotent.
In plain terms: “Give me this thing. I’m only looking. I’m not changing anything.”
The vast majority of web traffic is reading. A dedicated read-only verb lets browsers, caches, and crawlers make assumptions that keep the whole web fast and safe.
Walking into a shop and pointing at what you want to see. Nothing moves. Nothing changes.
There’s a wrinkle: a GET response can still be dynamic — personalised, generated on the fly, different every time. It’s still “safe” because the server’s state hasn’t changed, even though the response might be completely different from the last one.
The unbreakable rule: GET must never change anything on the server. No deleting. No updating. No creating. Ever.
Why so strict? Because browsers prefetch GET URLs, crawlers follow GET links, caches store GET responses, and bookmarks and history are built on GETs. If GET could delete something, all of that machinery would become a weapon.
POST — create
POST sends data to the server, usually to create a new resource.
POST /api/tasks
Content-Type: application/json
{ "title": "Finish Day 5", "done": false }
POST — An HTTP method that submits data to the specified resource, often causing a change in state or the creation of a new resource. Neither safe nor idempotent.
In plain terms: “Here’s some data. Do something with it — usually make a new thing.”
GET has no defined meaning for a request body — a server is free to ignore one — so something else had to carry data from client to server, and that something is POST. It’s also the catch-all verb: when no other method fits, POST is what you’re left with.
Submitting a form at a bank to open an account. But banks have anti-duplication safeguards. HTTP POST doesn’t. Submit it twice, get two accounts. The workaround — idempotency keys — is an application-layer invention, not part of the protocol.
POST is the odd one out: the only method that is neither safe nor idempotent. Send the same POST twice, get two different resources. This is why every serious payment processor uses idempotency keys — a trick to make POST behave idempotently even though it isn’t by default. For now, just remember: POST twice = two things.
PUT — replace
PUT replaces a resource entirely. You send the complete new version of the resource, and the server overwrites what was there.
PUT /api/tasks/42
Content-Type: application/json
{ "title": "Finish Day 5", "done": true }
PUT — An HTTP method that replaces all current representations of the target resource with the request payload. Not safe, but idempotent.
In plain terms: “Here’s the complete new version. Throw away whatever was there.”
Replacing an entire document. You hand over a fresh sheet of paper. The old one is gone.
Except servers usually preserve metadata you didn’t send — created_at, id, owner. A PUT that “replaces everything” still leaves server-managed fields intact. The client’s payload is the new user-facing state, not the whole database row.
PUT can also create. If you PUT to a URL that doesn’t exist yet and the server supports it, the resource springs into being at exactly that address. That’s the real reason PUT is idempotent and POST isn’t: with PUT the client chooses the address, so sending the same PUT twice lands in the same place twice. With POST the server chooses the address — and the server can’t tell a retry from a genuine second submission.
PUT is idempotent. Send the same PUT 100 times, the resource ends up in the same state as sending it once.
PATCH — update
PATCH updates a resource partially. You only send the fields you want to change.
PATCH /api/tasks/42
Content-Type: application/json
{ "done": true }
PATCH — An HTTP method that applies partial modifications to a resource. Not safe, and not guaranteed to be idempotent. Standardised in RFC 5789.
In plain terms: “I only want to change this one field. Leave the rest alone.”
PUT forces the client to send the whole resource for every change. If you only want to flip done from false to true, sending the entire task back is wasteful — and dangerous, because you might overwrite another user’s changes to a different field.
Editing a document with a text editor. You change one line and leave everything else.
A text editor preserves surrounding context automatically. HTTP PATCH doesn’t work that way. The format of the diff matters — JSON Merge Patch (RFC 7386) and JSON Patch (RFC 6902) behave differently, and “PATCH” alone doesn’t tell you which style is in play.
DELETE — remove
DELETE removes a resource.
DELETE /api/tasks/42
DELETE — An HTTP method that deletes the target resource. Not safe, but idempotent.
In plain terms: “Make this thing not exist anymore.”
Symmetry with the other CRUD operations. You can create, read, and update. You also need to remove.
Deleting a photo from your phone.
Except deleting a photo usually moves it to a Trash folder for 30 days. Most server-side “deletes” are also soft deletes — the record stays in the database, just flagged as gone. HTTP DELETE means removed from public view, not physically erased. Actual permanent deletion is a business decision, not a protocol requirement.
DELETE is idempotent. Deleting something twice is the same as deleting it once. After the first delete, the resource is gone. After the second, it’s still gone. No difference.
The three you’ll use rarely
HEAD is exactly like GET, except the server returns only the headers, not the body.
HEAD — An HTTP method identical to GET except that the server must not return a message body. Safe and idempotent.
In plain terms: “Tell me about this thing, but don’t send me the thing.”
Sometimes you only need the metadata. Downloading a 5MB file just to check whether it exists is wasteful. Calling a restaurant to ask “are you open?” without ordering food.
But a phone call is a two-way conversation. HEAD is a single request-response with a body-less reply. Nothing is negotiated.
OPTIONS asks the server: “What is allowed on this URL?”
OPTIONS /api/tasks
HTTP/1.1 200 OK
Allow: GET, POST, PUT, DELETE
OPTIONS — An HTTP method that requests information about the communication options available for the target resource. Safe and idempotent.
In plain terms: “What am I allowed to do here?”
Originally a discovery tool. Now used almost exclusively by browsers for CORS preflight — checking permission before sending a cross-origin request. We’ll cover CORS properly in a few days.
Knocking on a door and asking which entrances to use before entering. But OPTIONS doesn’t just report the doors — it’s how the server tells the browser which origins, headers, and methods are allowed in the first place. An active negotiation, not a passive directory.
CONNECT and TRACE exist. You will almost never use them directly. TRACE is disabled on almost every server because it’s a security risk. CONNECT is for tunnelling through proxies. Know they exist. That’s enough.
The two invisible properties
Methods look like a list of eight tokens. They’re actually classified by two properties that determine how they’re allowed to be used. Understanding these two properties is what separates people who use HTTP from people who design with it.
Safe method — An HTTP method whose defined semantics are read-only: the client does not request, and does not expect, any change to the state of the server.
In plain terms: “Reading, not writing. Nothing on the server changes because of this.”
Browsers, caches, crawlers, and prefetchers all need a way to know which requests are safe to fire without explicit user intent. Without this property, none of those systems could operate.
Reading a book versus writing in it. Reading changes nothing about the book.
Even a “read” can write metadata — logs, analytics counters, cache entries. “Safe” means no change to the target resource’s state, not no effect whatsoever. A safe request can still leave fingerprints.
Safe methods: GET, HEAD, OPTIONS, TRACE. Unsafe methods: POST, PUT, PATCH, DELETE.
Idempotent — A property of an HTTP method where multiple identical requests have the same intended effect on the server as a single request. From the Latin idem (same) + potens (power).
In plain terms: “Doing it twice is the same as doing it once.”
Networks are unreliable. When a request times out, the client doesn’t know whether the server received it. If the method is idempotent, the client can safely retry. If it isn’t, retrying risks duplicate side effects — double orders, double charges, duplicate accounts.
Pressing an elevator button. Press it once, press it ten times — the elevator comes once.
Elevator buttons don’t return anything. HTTP methods return responses too. Idempotence is about the effect on the server, not about the response being identical. Two identical DELETE calls can return different status codes — 200 then 404 — and still be idempotent.
Idempotent: GET, HEAD, PUT, DELETE, OPTIONS, TRACE. Not idempotent: POST, PATCH.
Here’s the full table:
| Method | Safe? | Idempotent? | Typical use |
|---|---|---|---|
| GET | ✅ | ✅ | Read |
| HEAD | ✅ | ✅ | Read headers only |
| OPTIONS | ✅ | ✅ | Ask what’s allowed |
| TRACE | ✅ | ✅ | Debug (rare) |
| POST | ❌ | ❌ | Create |
| PUT | ❌ | ✅ | Replace (or create) |
| PATCH | ❌ | ❌ † | Partial update |
| DELETE | ❌ | ✅ | Delete |
† PATCH is not guaranteed idempotent by the spec, though most JSON-based implementations in practice are.
Read this table three times. It’s interview gold.
CRUD, and the mapping everyone expects
You’ll hear the phrase CRUD constantly.
CRUD — Create, Read, Update, Delete — the four fundamental operations on persistent data.
In plain terms: the four things you can do to any record in a system.
Every application, from a to-do list to a bank, boils down to these four operations. Having a shared vocabulary makes system design simpler.
A notebook. You write in it (Create), read it (Read), edit an entry (Update), or tear a page out (Delete).
Except a notebook doesn’t have concurrent users, versioning, permissions, or distributed replicas. Real CRUD happens in systems where those constraints matter, and the four operations stop being symmetrical.
The HTTP method mapping is basically canon:
| CRUD | HTTP method |
|---|---|
| Create | POST |
| Read | GET |
| Update | PUT (full) or PATCH (partial) |
| Delete | DELETE |
REST is essentially this mapping, applied consistently across a whole API.
REST — Representational State Transfer — an architectural style for APIs, described by Roy Fielding in his 2000 doctoral dissertation, in which HTTP methods carry the action and URLs name resources.
In plain terms: “Use the verbs as intended, make your URLs nouns, and let the protocol do the work.”
We’ll do a proper REST day in Module 6.
The mistake that deletes things by accident
Here’s a real anti-pattern to avoid forever:
GET /delete-task?id=42
Never do this. Ever. GET is safe. It must not delete. If someone shares that URL, or a crawler visits it, or the browser prefetches it, the task is gone.
The correct version:
DELETE /tasks/42
Same effect. But now every tool that respects HTTP — browsers, caches, crawlers — knows not to fire this request casually.
GET is “show me the menu.” DELETE is “throw out this dish.” If you write a GET that deletes, you’ve written a “show me the menu” that throws out the dish. That’s not a web app. That’s a booby trap.
Backstory: how we ended up with these verbs
HTTP 1.0 (1996) had only three methods: GET, POST, and HEAD. That was it. You couldn’t PUT or DELETE anything — you just got things or posted things. It was a web of pages, not applications.
HTTP 1.1 (1997) added five more: PUT, DELETE, OPTIONS, TRACE, CONNECT. That’s when the modern method map was born.
PATCH — that quiet, useful method — is the newest of the bunch. It was formally introduced in RFC 5789, published in 2010. That’s right: PATCH is younger than Facebook, younger than the iPhone. Before PATCH, if you wanted to update a resource, you had to send the whole thing with PUT, or invent some non-standard endpoint. PATCH was the industry’s answer to “I just want to change one field.”
Even after PATCH was standardised, many APIs and frameworks resisted it for years. Some still do. If you ever see an API that uses POST /tasks/42/update instead of PATCH /tasks/42, you’re looking at a developer who hasn’t caught up with 2010.
One more piece of backstory worth knowing: the whole “verbs versus nouns” discipline was formalised by Roy Fielding in his 2000 PhD dissertation, which is where the term REST comes from. Fielding was one of the authors of the HTTP specification itself. He helped write the rules, then spent the next twenty years watching the industry argue about them.
What you’d say in the room
Two questions cover almost everything today’s lesson exists for.
If an interviewer asks “What’s the difference between PUT and PATCH?” — here’s the answer:
“PUT replaces the entire resource with the payload you send. PATCH applies a partial modification — you send only the fields you want to change. The practical difference is overwriting: if two clients edit different fields of the same record, PUT forces each of them to send the whole object, so the second write silently destroys the first. PATCH only touches the fields it names. The other difference is idempotence: PUT is idempotent by definition, PATCH isn’t guaranteed to be.”
The follow-up you should expect next is “Why does idempotence matter if the protocol delivers reliably?” — and here’s the answer:
“Because the reliability isn’t visible to the client. A request can time out after the server has already processed it, and the client has no way to know which of those two things happened. If the method is idempotent, the client can retry safely, because the second attempt has the same effect as the first. If it isn’t, a retry can double the effect — two orders, two charges, two accounts. That’s why payment APIs require an idempotency key: it’s the application inventing the property the method doesn’t have.”
Say it like a professional
The definitions from today, in one reviewable block. Say each one out loud. If you stumble, go back to that section.
- HTTP method — A token in the request line of an HTTP request that indicates the desired action to be performed on the target resource. The standard methods are GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE, and CONNECT.
- GET — An HTTP method that requests a representation of the specified resource. Safe and idempotent.
- POST — An HTTP method that submits data to the specified resource, often causing a change in state or the creation of a new resource. Neither safe nor idempotent.
- PUT — An HTTP method that replaces all current representations of the target resource with the request payload. Not safe, but idempotent.
- PATCH — An HTTP method that applies partial modifications to a resource. Not safe, and not guaranteed to be idempotent. Standardised in RFC 5789.
- DELETE — An HTTP method that deletes the target resource. Not safe, but idempotent.
- HEAD — An HTTP method identical to GET except that the server must not return a message body. Safe and idempotent.
- OPTIONS — An HTTP method that requests information about the communication options available for the target resource. Safe and idempotent.
- Safe method — An HTTP method whose defined semantics are read-only: the client does not request, and does not expect, any change to the state of the server. The safe methods are GET, HEAD, OPTIONS, and TRACE.
- Idempotent — A property of an HTTP method where multiple identical requests have the same intended effect on the server as a single request, so a client can safely retry after a timeout. From the Latin idem (same) + potens (power).
- CRUD — Create, Read, Update, Delete — the four fundamental operations on persistent data, and the vocabulary every API ends up mapping onto HTTP methods.
- REST — Representational State Transfer — an architectural style for APIs, described by Roy Fielding in 2000, in which HTTP methods carry the action and URLs name resources.
Before you close this tab
Don’t just answer. Reproduce. Say these out loud, in your own words, without looking. Then reopen the page and check.
- Define “HTTP method” formally.
- Give the formal one-liner for GET, POST, PUT, PATCH, and DELETE.
- What does “safe” mean? Which methods are safe?
- What does “idempotent” mean? Which methods are idempotent?
- What’s the difference between PUT and PATCH, formally?
- Why must GET never change server state? Name three pieces of web machinery that depend on it.
- What is HEAD for? What is OPTIONS for, in practice today?
- Map CRUD to HTTP methods.
- When was HTTP 1.1 released, and how many methods did it add?
- When was PATCH introduced, and what problem did it solve?
If you can say all ten out loud without peeking, Day 5 is done. If you can’t, pick the two or three you stumbled on and read those sections again. That’s the loop that turns recognition into recall.
Tomorrow
You now have verbs. You have a URL. You know how a request is shaped. But when the server answers, it starts with a number — three digits that tell you everything about how the request went.
Those numbers are status codes. They’re the reason a broken link shows a 404 and not a blank page. They’re why a payment failure and a wrong password can look identical to a user but be completely different to a developer. And they’re the thing you’ll read twenty times a day once you know what you’re looking at.
Tomorrow, we learn to read them.
Close the loop
0/3 sentences