Suppose a customer wants to change a reading list from a card layout to a compact layout. The request contains one new value, but what should happen to the saved caption and author-display setting? The answer depends on whether the client is replacing a resource's state or describing changes to it.
PUT and PATCH express different intentions.
This chapter compares their request semantics, omitted fields, patch formats, retry behavior, and practical trade-offs using a fictional bookstore API. Examples use JSON over HTTPS at https://api.bookstore.example.
PUT asks the server to create or replace the target resource's state with the state the supplied representation defines. PATCH asks it to apply changes a patch document describes. A patch document is a payload whose format defines how to modify the target.
The distinction is about meaning, not payload size. A replacement can be small because the resource is small. A patch can be large because it contains many operations or replaces a large nested value.
The diagram shows the two intentions:
A PUT can still depend on current permissions, business rules, and version conditions. The diagram distinguishes how the client expresses the requested state; it does not suggest that the service skips those checks.
Neither method is safe in HTTP terminology: both request state changes. Neither grants permission to write every field simply because the client can read it.
Define the target resource before deciding what “complete” means. Replacing a reading list's display settings should not replace its books, owner, or creation timestamp.
The bookstore exposes a small child resource at /reading-lists/list_801/display-settings. Its representation contains only display configuration:
The schema requires layout, which accepts cards or compact, and show_authors, which is a Boolean. caption is optional; when present, it is a string of 1–120 Unicode code points. Absence means no caption. Unknown fields and JSON null values are not valid stored settings.
The list ID belongs in the address and is not a writable settings field. The parent list's metadata and membership belong to other resource boundaries. Both PUT and PATCH on this address affect only display settings.
This API creates settings when it creates the list and makes both methods update-only. A missing or concealed target returns 404. PUT's ability to create resources does not force every endpoint to accept creation, and PATCH does not universally require an existing target.
The examples below are alternative requests against the same initial settings, not successive requests. Assume an authorized GET returned the representation above with the strong entity tag "display-801-v3". An entity tag is an opaque value that identifies a representation for validation. Clients send it back without interpreting its contents. Each request supplies that tag in If-Match to guard the state the client used to prepare it.
A small replacement boundary is often clearer than asking clients to send back a large resource containing internal, computed, and unrelated fields. PUT replaces API-defined state; it does not mean replacing an entire database row or deleting every related record.
Suppose the customer wants a compact layout that shows author names but has no caption. The complete replacement is:
The API replaces the settings and returns:
The caption is absent because this replacement schema defines omission of the optional caption as having no caption. The service does not carry Weekend reading forward from the old representation.
That does not mean the server must delete or assign null to every field a PUT omits. The resource schema determines whether omission is valid, selects a documented default, or causes rejection. Here, omitting required show_authors is invalid; omitting optional caption removes it from the replacement state. Neither behavior means “keep whatever the service currently stores.”
An intentionally invalid replacement illustrates the difference:
Because the required Boolean is missing, the API rejects the request without changing anything:
Quietly preserving the old value would make this endpoint behave like a merge despite advertising replacement semantics. The corrected PUT must include show_authors; a client intending only a layout change can use the supported PATCH contract instead.
The successful PUT response deliberately omits validators. HTTP permits validators in a successful PUT response only when the server saved the submitted representation data without transformation and the validator reflects that new representation. An implementation that normalizes or reserializes the submitted data must respect that restriction. A subsequent GET can provide the current representation and its tag for another edit.
Each HTTP JSON body occupies one line without a trailing newline. Credentials are placeholders.
Now suppose the customer's only intention is to change layout while preserving the remaining settings. With JSON Merge Patch, the request is:
The response preserves the author setting and caption:
For JSON Merge Patch objects, omitted members remain unchanged, the service merges supplied values according to the format, and null requests removal. Therefore, {"caption":null} removes this optional caption. It does not store a JSON null. Removing a required setting would fail the resulting-resource validation.
These rules come from application/merge-patch+json, not from PATCH alone. application/json identifies JSON syntax but does not, by itself, define a patch algorithm. An API can document custom JSON patch semantics, but consumers must not assume a universal meaning for them.
Another standard format, JSON Patch, uses application/json-patch+json and an array of explicit operations. On an endpoint supporting that format, a client could express the same layout change as:
This display-settings endpoint supports Merge Patch only; it does not accept the JSON Patch example. Supporting PATCH does not require supporting every patch media type. An unsupported format receives 415 Unsupported Media Type, with Accept-Patch: application/merge-patch+json advertising the supported format. Allow can advertise supported methods; it does not identify the patch format.
Patch formats also differ in how much data an edit replaces. A Merge Patch array value replaces that array as a whole; it does not imply element-by-element merging. Do not choose PATCH and assume the service automatically preserves every nested value.
The animation uses a separate customer-profile example to compare how PUT and PATCH update a phone number.
An operation is idempotent when repeating an identical request has the same intended effect as performing it once. PUT is idempotent by method semantics. Replacing the settings with the same representation twice does not mean creating two independent settings resources.
Idempotency does not require identical status codes, timestamps in operational logs, or response bytes. It also does not guarantee that no other client changes the resource between attempts.
PATCH has no method-wide idempotency guarantee. Assigning layout to compact through the Merge Patch example is idempotent with respect to that assignment. An operation that appends to an array can have a different effect each time.
For a separate JSON Patch illustration, assume a document has an existing notes array and accepts duplicate entries. This operation appends one note:
Without a condition or duplicate-request protection, applying it twice appends twice. The diagram compares the effects, assuming no intervening changes:
The operation's meaning determines whether repetition adds another effect. A patch can be idempotent, but clients cannot infer that from the method name.
Conditions add another part to retry behavior. If the settings update commits and the client never receives its response, a retry with the old tag may receive 412 Precondition Failed. That can happen for either PUT or PATCH. It does not prove the first attempt failed, and it does not contradict PUT's idempotency.
Do not silently reinterpret replacement or field assignment as “send another notification” each time a request arrives. Define any necessary business effects and their duplicate handling so retries do not produce unintended extra actions.
PUT's idempotency does not prevent lost updates. A client may replace settings from a stale copy and restore an old caption while changing only the layout in its user interface.
A narrow PATCH avoids assigning fields it does not mention, but competing writes to the same field can still overwrite one another. Updates to different fields can also violate a rule that relates those fields. Neither method eliminates the need for a concurrency policy.
This display-settings API requires If-Match and checks it atomically with the update. If another edit has changed the representation, an otherwise valid request with the old tag receives 412 and makes no changes. The client retrieves the current state and reviews its intended edit before retrying. Merely substituting the new tag into an old replacement defeats that protection.
The scope of the tag matters. A tag for the parent reading list is not automatically a validator for its display-settings resource. Use the validator for the representation the client is editing.
Choose the size of that resource deliberately. Keeping settings together can simplify their shared rules and replacement behavior, while splitting independent settings can reduce unnecessary conflicts. Do not split fields that need coordinated validation merely to reduce the number of rejected edits.
Both methods must produce an allowed resource state. PUT validates the replacement against the target's contract. PATCH validates its instructions and the state those instructions produce. A smaller request does not justify weaker validation.
PATCH requires atomic application: if the server cannot apply the complete patch, it applies none of its changes. This bookstore also commits each settings replacement as one unit. Clients never receive an error after the server has saved only some requested settings.
Permissions apply to the effects of a request. A PUT can remove optional fields through omission, so authorization must account for those removals as well as supplied values. PATCH must authorize the fields or paths it changes. Changing methods must not bypass a restriction.
A support user with read-only access cannot modify these settings through either method. For example:
No settings change. A caller who may not know the private list exists receives a generic 404 under the bookstore's concealment policy instead.
For completed changes to existing settings, this API returns 200 with the saved representation. A contract returning no content can use 204. If a permitted PUT creates a previously unrepresented target, HTTP requires 201 Created; this example's update-only policy does not allow that case. Do not use 201 merely because a storage implementation writes a new internal version.
Malformed payloads, unsupported formats, invalid resulting values, and failed version conditions are different failures. Keep those distinctions consistent across supported methods so clients can choose the method according to their intent rather than according to inconsistent error behavior.
PUT fits clients that manage the entire state of a well-defined resource: a saved configuration document, an uploaded artifact, or a small settings object. PATCH fits clients making focused changes while leaving other state under existing ownership or control.
Use this decision flow as a starting point:
The contract must still address permissions, validation, and conflicts whichever path you choose. Supporting both PUT and PATCH is useful only when consumers need both intentions and the service can keep their rules consistent.
Consider future fields before publishing replacement semantics. If an older client does not know about a newly added optional setting, its PUT may omit and remove that setting. Adding a required setting can instead make older replacements invalid. Even an apparently additive schema change can affect writers.
PATCH often reduces that particular risk because clients can leave unknown fields untouched. It does not make every evolution compatible: changing null behavior, allowed paths, validation rules, or array interpretation can still break clients.
Preserve the meaning the API already publishes. An endpoint that historically treats omitted PUT fields as unchanged cannot silently switch to replacement behavior without affecting existing integrations. Plan a deliberate contract migration. For a new API, align the method, resource boundary, and payload format from the beginning.
Use PUT to express replacement state and PATCH to express changes in a documented format. Define the target resource and omission rules precisely so clients know what the service will preserve, remove, or reject.
PUT is idempotent, while PATCH's repeat behavior depends on the operation. Both need validation, authorization, and a concurrency policy. Choose according to the client's intended control over the resource, and preserve that meaning as the API evolves.