
TL;DR
1. PUT replaces an entire resource; PATCH applies partial modifications to a resource.
2. Both PUT and PATCH methods are designed to be idempotent, ensuring consistent results upon multiple identical requests.
3. Choosing between PUT and PATCH depends on whether clients can send a full, valid representation of the resource or only the changes.
4. JSON Patch and JSON Merge Patch are common, standardized formats for specifying partial updates with PATCH.
5. Correct usage leads to more efficient network usage, clearer API semantics, and simplified client-side logic.
Crafting efficient and intuitive APIs often hinges on mastering the subtleties of HTTP methods, especially when it comes to updating resources. While `GET` and `POST` are relatively straightforward for retrieving and creating data, the choice between `PUT` and `PATCH` for modifying existing resources can often be a source of confusion. This decision is more than just a technical detail; it impacts network efficiency, data integrity, and the overall developer experience. Understanding the fundamental distinctions between these two update methods is crucial for designing robust, scalable, and semantically correct RESTful APIs. Delving into their specific use cases, characteristics like idempotency, and the implications of their implementation will empower you to make informed choices that streamline your API interactions and enhance the reliability of your data updates.
In the realm of API design, an update operation typically involves a client sending data to a server to modify an existing resource. The HTTP specification provides two primary methods for this purpose: `PUT` and `PATCH`. While both are used to alter server-side data, they operate with different semantic intentions and expectations regarding the request payload. Choosing the correct method is fundamental to adhering to REST principles, ensuring clarity in API contracts, and optimizing communication between client and server. A well-designed API leverages these distinctions to make interactions predictable, efficient, and resilient, which are hallmarks of REST API best practices.
The `PUT` method is used to replace a target resource's current representations with the content of the request payload. Think of it as a complete swap. When a client sends a `PUT` request, it is essentially saying, "Here is the *entire* new state of this resource; please replace whatever you currently have with this."
Imagine an API for managing user profiles. A `User` resource might have fields like `id`, `firstName`, `lastName`, `email`, `address`, and `phone`. If a client wants to update a user's `firstName` and `lastName`, a `PUT` request would require sending the entire user object, even if `email`, `address`, and `phone` remain unchanged.
Request:
PUT /users/123
Content-Type: application/json
{
"id": "123",
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com",
"address": "123 Main St",
"phone": "555-1234"
}
If the client only sent `{"firstName": "Jane", "lastName": "Doe"}` in a `PUT` request, the server would likely wipe out or nullify the `email`, `address`, and `phone` fields for user `123` because they were omitted from the *full* representation provided.
The `PATCH` method is used to apply partial modifications to a resource. Unlike `PUT`, which demands a complete resource representation, `PATCH` allows clients to send only the specific changes they want to make. This makes `PATCH` ideal for granular updates where only a few fields need to be altered without affecting others.
Using the same `User` resource example, if the client only wants to update a user's `firstName` and `lastName`, a `PATCH` request would only send those specific fields:
Request:
PATCH /users/123
Content-Type: application/json
{
"firstName": "Jane",
"lastName": "Doe"
}
In this `PATCH` scenario, the server would update only `firstName` and `lastName` for user `123`, leaving `email`, `address`, and `phone` untouched. This is the primary distinction that makes `PATCH` powerful for granular updates.
Because `PATCH` allows for partial modifications, the format of the request payload is critical. Unlike `PUT`, where the payload is simply the full representation of the resource, `PATCH` needs a way to describe *what* changes should be applied. Two common, standardized formats address this:
Description: JSON Patch defines a JSON document that expresses a sequence of operations to apply to a target JSON document. It's a precise, instruction-based format that supports operations like `add`, `remove`, `replace`, `move`, `copy`, and `test`.
Precision: It offers granular control, allowing clients to modify specific elements within an array, add fields, remove fields, or even test for existing values before applying a change.
Example: To change a user's `firstName` and `lastName`:
PATCH /users/123
Content-Type: application/json-patch+json
[
{ "op": "replace", "path": "/firstName", "value": "Jane" },
{ "op": "replace", "path": "/lastName", "value": "Doe" },
{ "op": "remove", "path": "/email" }
]
Use Case: Ideal when precise, fine-grained control over modifications is needed, or when changes involve complex structures like arrays. Often used in scenarios where the client needs to convey a "diff" from a known state.
Description: JSON Merge Patch is a simpler format where the request body is a partial JSON document. The server then "merges" this partial document with the existing resource. If a field exists in both, the value from the `PATCH` document replaces the existing value. If a field is present in the `PATCH` document but not in the original, it's added. If a field is explicitly set to `null` in the `PATCH` document, it's removed from the resource (or set to `null` if `null` is a valid value for that field).
Simplicity: It's easier to generate from a client's perspective, often just sending the fields that have changed.
Example: To change a user's `firstName` and `lastName`:
PATCH /users/123
Content-Type: application/merge-patch+json
{
"firstName": "Jane",
"lastName": "Doe",
"email": null // This would remove or nullify the email field
}
Use Case: Best for simple updates where fields are added, updated, or removed, and the primary concern is sending a subset of data. It's less suitable for array manipulations or very specific, instruction-based modifications.
While using a generic `application/json` content type for `PATCH` requests is common and often implies JSON Merge Patch semantics, explicitly using `application/json-patch+json` or `application/merge-patch+json` as the `Content-Type` header clarifies the intent and processing method for the server.
To solidify the understanding of these two update methods, here's a direct comparison of their key attributes:
Choosing `PUT` is appropriate when the client's intent is to completely replace an existing resource with a new, authoritative representation. Consider these scenarios:
The key takeaway for `PUT` is that the request payload is the *definitive* state of the resource you want to exist on the server. Anything not included is implicitly considered "gone" or "reset."
`PATCH` shines when the client needs to apply specific, incremental changes to a resource without providing its full representation. It's the method of choice for targeted updates:
The crucial distinction for `PATCH` is that the request payload is an *instruction set* or a *delta* describing how to transform the current state of the resource. The server must intelligently apply these changes, preserving unmentioned fields.
Idempotency is a cornerstone of robust API design, especially for update operations. An operation is idempotent if executing it multiple times produces the same result as executing it once. This property is vital for systems operating over unreliable networks, where requests might be retried due to timeouts or other transient failures.
Ensuring idempotent update operations provides predictability and resilience against network glitches and client-side retry mechanisms, leading to a more stable and reliable API ecosystem.
Beyond the core semantics, the choice and implementation of `PUT` and `PATCH` have broader implications for the performance and maintainability of your API.
Correctly distinguishing between `PUT` and `PATCH` in your API monitoring tools can provide clearer insights into how clients are interacting with your API. For example, a high volume of `PUT` requests might indicate clients are sending full resource representations unnecessarily, while complex `PATCH` errors could signal issues with client-side patch generation or server-side merging logic. Using best API monitoring tools can help track these patterns.
Both `PUT` and `PATCH` are typically seen as write operations and should be subject to rate limiting to protect your backend resources from abuse. While `PATCH` might appear lighter on bandwidth, the computational cost on the server for merging changes could be higher, making consistent rate limiting crucial.
Clear semantics help developers. When they understand whether to send a full resource or a partial one, they write more efficient and less error-prone client code. Good API developer portal documentation should clearly specify which method to use and what payload formats are expected.
Thoughtful selection of `PUT` or `PATCH` contributes to a more efficient and understandable API that is easier to maintain and scale over time, integrating well with your broader API gateway and API management strategies.
Regardless of whether you choose `PUT` or `PATCH`, adhering to certain best practices will ensure your update endpoints are robust, secure, and developer-friendly.
By following these best practices, you can build update endpoints that are not only functional but also reliable, secure, and a pleasure for developers to integrate with.
`PUT` is semantically correct for full resource updates where the client sends the entire, new state of the resource. It's often simpler to implement on the server side (a direct overwrite). However, if clients frequently lack the full resource state or only need to change a few fields, `PATCH` might be more efficient in terms of bandwidth and can be preferable for targeted updates, even if it adds server-side complexity for merging changes.
No, `PATCH` is strictly for modifying an existing resource. If a `PATCH` request is sent to a URI where no resource exists, the server should respond with `404 Not Found`. Resource creation is primarily handled by the `POST` method, or occasionally by `PUT` when the client determines the resource's URI.
If you omit a field in a `PUT` request, the server is expected to treat that field as if it were explicitly set to `null` or its default value, or even removed, effectively overwriting the previous state. The `PUT` method signifies a *complete* replacement, so any missing data in the payload is considered intentional and will alter the resource accordingly.
JSON Patch (RFC 6902) is an instruction-based format that specifies a sequence of operations (add, remove, replace, move, copy, test) to apply. It offers precise control, especially for arrays. JSON Merge Patch (RFC 7386) is a simpler, data-driven format where the payload is a partial JSON document that gets merged with the existing resource. If a field is `null` in a JSON Merge Patch, it's typically interpreted as a removal. JSON Patch is more powerful for complex, precise changes, while JSON Merge Patch is easier to generate for simple field updates.
Idempotency is crucial because it ensures that performing the same operation multiple times has the same effect as performing it once. In distributed systems, network issues can lead to clients retrying requests without knowing if the original request succeeded. For idempotent methods like `PUT` (and carefully implemented `PATCH`), clients can safely retry without fear of creating duplicate resources, introducing inconsistencies, or causing unintended side effects, thus enhancing the API's reliability and resilience.