Definition
- PUT – performs a full replacement of a resource; the body is the entire new representation, so any omitted field is set to default or cleared.
- PATCH – performs a partial update; the client sends only the changed fields, and the server leaves every other field untouched.
- Idempotency – PUT is idempotent by definition because sending the same full body twice produces the same state; PATCH is not guaranteed idempotent.
- Validation – PUT validates the full object because every field must be present; PATCH validates only the fields that are present.
- Null handling – a simple merge-patch cannot distinguish between "field is null" (delete it) and "field is absent" (do not touch it), which is why JSON Merge Patch and JSON Patch formats exist.
Think of Priya's profile form at National Bank of India. PUT is like handing the clerk a brand new, fully filled form that completely replaces the old one: if you left the phone number blank, the clerk erases the old phone number too, because the new form is now the truth. PATCH is like handing the clerk a sticky note that says "only change the phone number to this": everything else on the existing form stays exactly as it was.
Understanding the Concepts
What is PUT?
PUT replaces a resource at a known URL with the representation in the request body. The mental model is that the body becomes the complete new state of that resource. If Priya's beneficiary has four fields and you PUT a body with only three, the fourth is treated as absent and becomes null or default, because PUT means "this is the whole thing now."
package com.bank.controller;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/v1/beneficiaries")
public class BeneficiaryController {
// PUT: full replacement. Omitting ifsc means ifsc becomes null.
@PutMapping("/{id}")
public BeneficiaryResponse replace(@PathVariable String id,
@RequestBody BeneficiaryRequest body) {
return beneficiaryService.replace(id, body);
}
}
What is PATCH?
PATCH applies a partial modification. The client sends only the fields it wants to change, and the server merges them into the existing resource. Fields not mentioned are left exactly as they were.
// PATCH: partial merge. Only non-null fields are applied.
@PatchMapping("/{id}")
public BeneficiaryResponse patch(@PathVariable String id,
@RequestBody PatchBeneficiaryRequest body) {
return beneficiaryService.patch(id, body); // only changes sent fields
}
How are PUT and PATCH different? (Comparison table)
| Aspect | PUT | PATCH |
|---|---|---|
| Scope | Full replacement | Partial modification |
| Missing fields | Cleared or set to default | Left untouched |
| Idempotent | Yes, by definition | Not guaranteed |
| Body contains | Complete resource representation | Only changed fields |
| Validation | Validate all fields | Validate only present fields |
| Content-Type | application/json | application/json or application/json-patch+json |
| Use when | Client submits a complete form | Client edits one or two fields |
// PUT body: every field present – full replacement.
// PUT /api/v1/beneficiaries/BEN-77
// {
// "name": "Priya Sharma",
// "accountNumber": "SAV3001",
// "ifsc": "NBI0001234",
// "nickname": "Landlord"
// }
// → All four fields replaced. If ifsc were missing, it becomes null.
// PATCH body: only the changed field.
// PATCH /api/v1/beneficiaries/BEN-77
// {"nickname": "Landlord"}
// → Only nickname changes. accountNumber, ifsc, name stay.
Why is PUT idempotent but PATCH is not?
PUT is idempotent because sending the same complete body twice ends in the same state. The second PUT overwrites with identical values, so there is no additional effect.
PATCH is not guaranteed idempotent because the specification does not require it. A PATCH that says "add 100 to the balance" runs twice and adds 200. A PATCH that sets an absolute value, like "set nickname to Landlord," happens to be idempotent, but you must treat PATCH as non-idempotent unless you designed it otherwise.
// PUT is idempotent: same body twice → same state.
// PUT /api/v1/beneficiaries/BEN-77 {full body} → state A
// PUT /api/v1/beneficiaries/BEN-77 {full body} → state A (identical)
// PATCH is NOT guaranteed idempotent:
// PATCH /api/v1/accounts/SAV2001 {"addToBalance": 100} → balance 1100
// PATCH /api/v1/accounts/SAV2001 {"addToBalance": 100} → balance 1200 (different!)
How do you handle null in PATCH?
There is a subtlety with PATCH and null. If Priya wants to clear a field, a simple "ignore nulls" merge cannot distinguish between "set this to null" and "do not touch this." Three approaches handle it:
- Convention: null means skip – simple but cannot clear a field.
- JSON Merge Patch (RFC 7396) – explicit null means delete the field.
- JSON Patch (RFC 6902) – uses a
removeoperation for explicit deletion.
// JSON Merge Patch: explicit null means delete.
// PATCH /api/v1/beneficiaries/BEN-77
// Content-Type: application/merge-patch+json
// {"ifsc": null, "nickname": "Landlord"}
// → ifsc is deleted, nickname is set to "Landlord"
// JSON Patch: explicit remove operation.
// PATCH /api/v1/beneficiaries/BEN-77
// Content-Type: application/json-patch+json
// [
// {"op": "remove", "path": "/ifsc"},
// {"op": "replace", "path": "/nickname", "value": "Landlord"}
// ]
How does validation differ between PUT and PATCH?
For PUT, you validate the full object because every field must be present and valid. For PATCH, you validate only the fields that are present, because the missing fields are intentionally absent and should not trigger required-field errors.
package com.bank.dto;
import jakarta.validation.constraints.*;
import java.math.BigDecimal;
// PUT request: every field is required.
public record BeneficiaryRequest(
@NotBlank String name,
@NotBlank String accountNumber,
@NotBlank String ifsc,
@NotBlank String nickname) {}
// PATCH request: all fields are optional.
public record PatchBeneficiaryRequest(
String name, // null means "do not change"
String accountNumber,
String ifsc,
String nickname) {}
What are common mistakes with PUT and PATCH?
The most common mistake is using PUT when only one field changes, which silently clears every field not included. Another is implementing PATCH incorrectly by treating a missing field and an explicit null the same way, losing the ability to clear a field.
// Wrong: PUT with only one field – everything else is cleared.
// PUT /api/v1/beneficiaries/BEN-77
// {"nickname": "Landlord"}
// → name, accountNumber, ifsc all become null!
// Correct: use PATCH for partial updates.
// PATCH /api/v1/beneficiaries/BEN-77
// {"nickname": "Landlord"}
// → Only nickname changes, everything else preserved.
When should you use PUT vs PATCH?
Use PUT when the client submits a complete form, such as full KYC re-submission, where every field is intentionally provided. Use PATCH when the client edits one or two fields, like changing a nickname or phone number. In banking, PATCH is far more common for day-to-day edits, while PUT is used for formal full re-submissions.
// Use PUT: customer re-submits the entire KYC form.
// PUT /api/v1/customers/C001/kyc {name, address, pan, aadhaar, photo, ...}
// Use PATCH: customer changes only their phone number.
// PATCH /api/v1/customers/C001 {"phone": "+91-9876543210"}
What should a senior engineer know about PUT vs PATCH?
A senior engineer knows that the controller should never see the entity directly. The service layer maps the request DTO to the entity, applying merge logic for PATCH. They know that many teams implement PATCH incorrectly, and the correct approach is to adopt JSON Merge Patch or JSON Patch semantics and document them clearly. They also know that PUT can create a resource if the client controls the ID, acting as an upsert.
Visual Overview
┌───────────────────────────────────────────────────────────┐
│ PUT vs PATCH Comparison │
├───────────────────────────────────────────────────────────┤
│ │
│ PUT /beneficiaries/BEN-77 │
│ Body: {name, account, ifsc, nickname} │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────┐ │
│ │ Server: REPLACE entire resource │ │
│ │ ┌────────┬──────────┬──────┬──────┐ │ │
│ │ │ name │ account │ ifsc │ nick │ │ │
│ │ │ NEW │ NEW │ NEW │ NEW │ │ │
│ │ └────────┴──────────┴──────┴──────┘ │ │
│ │ Missing field? → becomes null │ │
│ └─────────────────────────────────────┘ │
│ │
│ PATCH /beneficiaries/BEN-77 │
│ Body: {nickname: "Landlord"} │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────┐ │
│ │ Server: MERGE only sent fields │ │
│ │ ┌────────┬──────────┬──────┬──────┐ │ │
│ │ │ name │ account │ ifsc │ nick │ │ │
│ │ │ OLD │ OLD │ OLD │ NEW │ │ │
│ │ └────────┴──────────┴──────┴──────┘ │ │
│ │ Missing field? → stays as-is │ │
│ └─────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────┘
Key Takeaway
PUT and PATCH both update a resource but they mean very different things. PUT is a full replacement: the client sends the complete representation, and the server replaces the entire resource, so any field the client leaves out is cleared or set to default. PATCH is a partial update: the client sends only the fields it wants to change, and the server leaves every other field exactly as it was.
A direct consequence is idempotency. PUT is idempotent because sending the same full body twice ends in the same state both times, which makes it safe to retry after a timeout. PATCH is not guaranteed idempotent, because a PATCH that expresses a relative change like "add one hundred to the balance" would stack up if repeated.
At National Bank of India this distinction prevented a real bug. Priya wanted to change only the nickname of her saved landlord beneficiary. When the app sent only the nickname through an endpoint that behaved like PUT, the account number and IFSC were wiped out because PUT treats missing fields as cleared, and her next rent payment failed. The fix was to use PATCH for partial edits so only the nickname changed and the other fields survived, and to reserve PUT for cases where the customer genuinely re-submits a complete form such as full KYC.
The careful detail is validation and null handling. For PUT, validate the full object because every field must be present. For PATCH, validate only the fields that are present. And because a simple ignore-nulls merge cannot tell the difference between "change this to null" and "do not touch this," adopt JSON Merge Patch where null means delete, or JSON Patch for fully explicit operations. Choosing the right verb and being precise about missing fields is what keeps partial updates safe.
Remember one sentence: PUT replaces the whole resource and clears missing fields, while PATCH changes only the fields you send and leaves everything else untouched.
---