HTTP

Method

HTTP PATCH Method

Learn how HTTP PATCH requests apply partial modifications to resources. Understand JSON Patch, merge patch formats, and when to use PATCH vs PUT.

5 min read intermediate Try in Playground

What is PATCH?

TL;DR: PATCH updates specific parts of a resource without replacing everything. Use it to modify individual fields like changing a user’s email or updating a post’s status.

PATCH is the HTTP method for making partial updates to a resource. Think of it like editing a document—you change specific parts without rewriting the entire thing.

PATCH is like saying “change just these specific fields” rather than “replace everything” (PUT) or “create something new” (POST).

Key Characteristics

1. Partial Updates

PATCH only modifies the fields you specify. Other fields remain unchanged, unlike PUT which replaces the entire resource.

Original: {"name": "John", "age": 25, "city": "NYC"}
PATCH: {"age": 26}
Result: {"name": "John", "age": 26, "city": "NYC"}

2. Not Always Idempotent

PATCH may or may not be idempotent depending on the operation. Simple field updates are idempotent, but operations like “increment by 1” are not.

✅ Idempotent: {"age": 26}
❌ Not idempotent: {"age": "current + 1"}

3. Not Safe

PATCH requests change server state by modifying resources. Unlike GET, PATCH has side effects.

4. Flexible Format

PATCH can use different formats like JSON Patch, JSON Merge Patch, or simple field updates.

How PATCH Works

1. Client sends partial update:

PATCH /users/42 HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
  "email": "newemail@example.com",
  "age": 30
}
```text

**2. Server updates only specified fields:**

```http
HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": 42,
  "name": "Jane Doe",
  "email": "newemail@example.com",
  "age": 30,
  "department": "Engineering",
  "updatedAt": "2026-01-18T10:30:00Z"
}

Notice how name and department stayed the same—only email and age were updated.

Real-World Examples

Example 1: Updating User Profile

PATCH /users/42 HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer abc123

{
  "bio": "Updated bio text",
  "profilePicture": "https://example.com/new-pic.jpg"
}
```text

**Response:**

```http
HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": 42,
  "name": "Jane Doe",
  "email": "jane@example.com",
  "bio": "Updated bio text",
  "profilePicture": "https://example.com/new-pic.jpg",
  "updatedAt": "2026-01-18T10:30:00Z"
}

Example 2: Changing Post Status

PATCH /posts/15 HTTP/1.1
Host: blog.example.com
Content-Type: application/json

{
  "status": "published",
  "publishedAt": "2026-01-18T10:30:00Z"
}
```text

**Response:**

```http
HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": 15,
  "title": "My Blog Post",
  "content": "Original content stays the same...",
  "status": "published",
  "publishedAt": "2026-01-18T10:30:00Z",
  "updatedAt": "2026-01-18T10:30:00Z"
}

Example 3: JSON Patch Format

PATCH /users/42 HTTP/1.1
Host: api.example.com
Content-Type: application/json-patch+json

[
  { "op": "replace", "path": "/email", "value": "new@example.com" },
  { "op": "add", "path": "/skills/-", "value": "JavaScript" },
  { "op": "remove", "path": "/temporaryField" }
]
```text

### Example 4: Toggling Settings

```http
PATCH /settings/notifications HTTP/1.1
Host: app.example.com
Content-Type: application/json

{
  "emailNotifications": false,
  "pushNotifications": true
}

Example 5: Updating Array Elements

PATCH /projects/5 HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
  "tags": ["web", "api", "tutorial"],
  "priority": "high"
}
```text

## When to Use PATCH

**✅ Use PATCH for:**

- Updating specific fields of a resource
- Changing user preferences or settings
- Modifying status or state fields
- Adding/removing items from arrays
- Partial form submissions
- Toggling boolean values

**❌ Don't use PATCH for:**

- Replacing entire resources (use PUT)
- Creating new resources (use POST)
- Operations that need to be strongly idempotent
- When you want to reset fields to defaults

## PATCH vs Other Methods

| Feature                | PATCH                   | PUT                     | POST                |
| ---------------------- | ----------------------- | ----------------------- | ------------------- |
| **Purpose**            | Update part of resource | Replace entire resource | Create new resource |
| **Idempotent**         | Sometimes               | Yes                     | No                  |
| **Partial updates**    | Yes                     | No                      | N/A                 |
| **Creates if missing** | Usually no              | Yes                     | Yes                 |
| **Fields not sent**    | Unchanged               | Removed/reset           | N/A                 |

### PATCH vs PUT Example

**Existing resource:**

```json
{
  "id": 42,
  "name": "John",
  "email": "john@example.com",
  "age": 25,
  "department": "Sales"
}

PATCH (partial update):

PATCH /users/42
{"age": 26}

→ Result: {"id": 42, "name": "John", "email": "john@example.com", "age": 26, "department": "Sales"}
```text

**PUT (complete replacement):**

```http
PUT /users/42
{"age": 26}

→ Result: {"id": 42, "age": 26} (name, email, department removed!)

PATCH Formats

1. JSON Merge Patch (Simple)

Most common format—just send the fields to update:

PATCH /users/42 HTTP/1.1
Content-Type: application/json

{
  "email": "new@example.com",
  "age": 30
}
```text

### 2. JSON Patch (RFC 6902)

More powerful format with specific operations:

```http
PATCH /users/42 HTTP/1.1
Content-Type: application/json-patch+json

[
  { "op": "replace", "path": "/email", "value": "new@example.com" },
  { "op": "add", "path": "/skills", "value": ["JavaScript", "Python"] },
  { "op": "remove", "path": "/oldField" }
]

JSON Patch Operations:

  • replace - Change a value
  • add - Add a new field or array item
  • remove - Delete a field
  • move - Move a value to a different location
  • copy - Copy a value to a new location
  • test - Verify a value before applying changes

Common Response Codes

CodeMeaningWhen Used
200OKResource successfully updated
204No ContentUpdated successfully, no response body
400Bad RequestInvalid patch format or data
401UnauthorizedAuthentication required
403ForbiddenNot allowed to modify this resource
404Not FoundResource doesn’t exist
409ConflictUpdate conflicts with current state
422UnprocessableValidation failed

Best Practices

1. Only send fields that changed

// ❌ Bad: Sending unchanged fields
fetch('/users/42', {
  method: 'PATCH',
  body: JSON.stringify({
    name: 'John', // unchanged
    email: 'john@example.com', // unchanged
    age: 26 // only this changed
  })
})

// ✅ Good: Only changed fields
fetch('/users/42', {
  method: 'PATCH',
  body: JSON.stringify({
    age: 26
  })
})
```javascript

**2. Handle missing resources gracefully**

```javascript
// Server should return 404 if resource doesn't exist
app.patch('/users/:id', (req, res) => {
  const user = findUser(req.params.id)

  if (!user) {
    return res.status(404).json({ error: 'User not found' })
  }

  // Apply partial update
  const updatedUser = { ...user, ...req.body }
  saveUser(updatedUser)
  res.json(updatedUser)
})

3. Validate patch operations

// Ensure patch doesn't violate business rules
const allowedFields = ['name', 'email', 'age', 'bio']
const invalidFields = Object.keys(req.body).filter((field) => !allowedFields.includes(field))

if (invalidFields.length > 0) {
  return res.status(400).json({
    error: `Cannot update fields: ${invalidFields.join(', ')}`
  })
}
```javascript

**4. Consider atomic operations**

```javascript
// For complex patches, use transactions
await db.transaction(async (trx) => {
  await trx('users').where('id', userId).update(userFields)
  await trx('profiles').where('userId', userId).update(profileFields)
})

Try It Yourself

Visit our playground to experiment with PATCH:

  1. Select PATCH as the method
  2. Try path /posts/1 to update an existing post
  3. Send partial JSON data:
    {
      "title": "Updated Title Only"
    }
  4. Notice how only the title changes, other fields stay the same!
  • PUT - Replace entire resources
  • POST - Create new resources
  • GET - Retrieve resources
  • DELETE - Remove resources

In Practice

Express.js
// PATCH /users/:id — partial update (JSON Merge Patch)
app.patch('/users/:id', async (req, res) => {
  // Only update fields present in the body
  const user = await db.users.update(req.params.id, req.body)
  if (!user) return res.status(404).json({ error: 'Not found' })
  res.json(user)
})

// Client sends only changed fields:
// PATCH /users/42  { "email": "new@example.com" }
// Other fields (name, role, etc.) are untouched
Next.js App Router
// app/api/users/[id]/route.ts
export async function PATCH(
  request: Request,
  { params }: { params: { id: string } }
) {
  const patch = await request.json()
  // Merge patch — only provided fields are updated
  const user = await db.users.update(params.id, patch)
  if (!user) return new Response(null, { status: 404 })
  return Response.json(user)
}
Django
# views.py
import json
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def user_detail(request, user_id):
    if request.method == 'PATCH':
        data = json.loads(request.body)
        # Only update provided fields
        User.objects.filter(pk=user_id).update(**data)
        return JsonResponse(User.objects.get(pk=user_id).to_dict())

Frequently Asked Questions

What is the HTTP PATCH method?

PATCH applies partial modifications to a resource. Unlike PUT which replaces the entire resource, PATCH only updates the specified fields.

What is the difference between PATCH and PUT?

PUT replaces the entire resource with the request body. PATCH applies partial changes. Use PUT for full replacement, PATCH for updating specific fields.

Is PATCH idempotent?

PATCH is not guaranteed to be idempotent. The same patch applied twice might have different effects. Design your patches to be idempotent when possible.

What format should PATCH use?

Common formats are JSON Merge Patch (application/merge-patch+json) and JSON Patch (application/json-patch+json). Plain JSON with partial data also works.

Keep Learning