REST – PUT vs POST

Last Updated :

This has been observed that many people struggle to choose between HTTP PUT and HTTP POST methods when designing a system.

Though, RFC 2616 has been very clear in differentiating between the two – yet complex wordings are a source of confusion for many of us.

Let’s try to solve the puzzle of when to use PUT or POST methods.

1. Difference between PUT and POST

PUT
POST
RFC-2616 clearly mention that PUT method requests for the attached entity (in the request body) to be stored into the server which hosts the supplied Request-URI.

If the Request-URI refers to an already existing resource – an update operation will happen, otherwise create operation should happen if Request-URI is a valid resource URI (assuming the client is allowed to determine resource identifier).
PUT /questions/{question-id}
The POST method is used to request that the origin server accept the entity attached in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line.

It essentially means that POST request-URI should be of a collection URI.
POST /questions
PUT method is idempotent. So if we retry a request multiple times, that should be equivalent to a single request invocation.
POST is NOT idempotent. So if we retry the request N times, we will end up having N resources with N different URIs created on the server.
Use PUT when we want to modify a singular resource that is already a part of resources collection.

PUT replaces the resource in its entirety. Use PATCH if request updates part of the resource.
Use POST when you want to add a child resource under resources collection.
Though PUT is idempotent, we should not cache its response.
Responses to this method are not cacheable, unless the response includes appropriate Cache-Control or Expires header fields.

However, the 303 (See Other) response can be used to direct the user agent to retrieve a cacheable resource.
Generally, in practice, use PUT for UPDATE operations.
Always use POST for CREATE operations.

2. PUT vs POST with Example

Let’s say we are designing a network application. Let’s list down a few URIs and their purpose to get a better understanding of when to use POST and when to use PUT operations.

GET 	/device-management/devices       : Get all devices
POST 	/device-management/devices       : Create a new device

GET 	/device-management/devices/{id}   : Get the device information identified by "id"
PUT 	/device-management/devices/{id}   : Update the device information identified by "id"
DELETE	/device-management/devices/{id}   : Delete device by "id"

Follow similar URI design practices for other resources as well.

Reference: SO Thread

Was this article helpful?

Comments

  1. I have one field added to HR Cloud for al employees. I want to update that field to a value, say, “False”. How to achieve via a Put query for that ?

    Reply
  2. I was doing an Upload test for 5G networks,
    My PUT tasks yielded more throughput(almost double) than POST tasks.
    Any idea why the data speed of uploading is influenced by PUT and POST differently?

    Any help is highly appreciable 🙂

    BR//
    Dinu

    Reply
  3. What should be the typical/appropriate HTTP status code returned when attempting to PUT when no record exists. Vice versa, what status to return when attempting a POST on an existing record?

    Reply
    • Hey Eric,

      You can send status 404 (Not Found) if an entry does not exist.

      For POST on an existing record, i think you can use a 401 Bad Request, I am not sure about this.

      Do look at this article.

      Reply
    • According to https://www.ietf.org/rfc/rfc2616.txt Section 9.4:

      “If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.”

      “… can create the resource …” implies that it’s up to you to either create the resource or not

      Reply
  4. the rfc link points to a obsolete resource. This is the proposed one for http 1.1 https://tools.ietf.org/html/rfc7231

    the text says:
    The target resource in a POST request is intended to handle the enclosed representation according to the resource’s own semantics

    to me this means that POST is more flexible than PUT, put should only create a new entity if doesn’t exists or update existing one. POST can create a new entity or do anything else.

    Reply
    • Good question. I believe it boils down to one being idempotent (PUT) versus non-idempotent (POST). Idempotent is all about cause and effect; given a single cause, is the effect limited or widespread. In this context, how many times can you issue a command (PUT or POST) and have the outcome update/create one and only one resource (PUT) or produce multiple resources in correlation to the number of time you invoked the command (POST).

      So if you only want ONE resource to be affected regardless of how many times you make a call, then PUT is the right command. If you want 10 or 20 resources to be affected (created), then you’d call the POST command 10 or 20 times, respectively.

      Reply
    • If the ID is generated externally you should use PUT to create new entities. e.g. if you use employeeId generated in a different system and you want to create an employee object in your system, you can safely use PUT for both creates and updates.
      It is idempotent, request can be repeated, the first one will create a record and the further requests will update (with the same value). Idempotent calls are safer.
      However, if the ID is generated by the target system you cannot use PUT, you need to provide POST operation. e.g. if your accounting system records invoices generation unique invoice numbers, then an external system cannot create a new invoice with PUT accounting/invoice/{ID} as the id does not exist yet. A POST accounting/invoice/ can be used and the ID is generated by the system.

      Reply
      • We can use PUT method even the ID is generated by target system.Its just an standard to use POST for inserting new record and PUT for updating existing record.

        If I am wrong correct me?

        Reply
        • In my opinion, or rather in my interpretation, a PUT without a client provided ID cannot be idempotent because there is nothing in the URI that identifies the singular resource that is being “PUT”.

          Technically you could allow the server to determine the identity of the resource by examining a known identifier within the body of the PUT request.

          However, I believe the beauty of idempotence as it pertains to HTTP requests is in the URI being the single determining factor of identification because of the fact that it is by definition a uniform resource identifier.

          Reply
  5. What will happen if I am calling the POST request with same employee ID.
    First time it will create the new resource and the next time i am calling with same identifier then what exception i will get or what will happen,

    Reply
    • You cannot call a POST request with a parameter. POST request-URI should be of a collection URI for eg /device-management/devices

      Reply
      • And even in your request body, you cannot pass employee ID as you will not have one if it’s a genuine POST request, you can only pass an Employee object without an Id

        Reply
  6. Hi, I’ve a question regarding using PUT both for creation and updating.

    For our addresses API, we can identify a unique address by it’s customer id (that owns it) and the address type it is (Communications/Billing/Delivery etc.).

    Each customer are allowed to have any number of addresses so long as they are each a unique address type.

    Essentially each address in the system can be identified by a combination of the customer id and an address type code.

    As such, we settled with allowing clients to create or update a specific address by sending a PUT request to a URL of the structure …/addresses/{customerId}/{addressTypeCode}, e.g., …/addresses/1234/COM

    If no address exists, it is created

    If an address exists, it is updated

    For consistency, we treat non-existent addresses as blank addresses, so if a GET is sent to …/addresses/1234/COM and no Communications Address exists for this customer, then a blank address is returned.

    I’m curious whether this is in violation of the intended use of PUT and POST. My view is that if your resource is using a natural id, then there’s no need to POST to the collection to generate an id.

    Reply
    • Thanks for sharing this. I have seen a lot of implementations like this in enterprise size companies, and they are perfectly serving their purpose. I also do not see it as a violation of PUT method contract.

      Reply
        • Thanks for asking this question. I am not too familiar with the graphql, it’s pros and cons. But on first look, I find it useful in some specific cases; similar to nosql databases.

          Also, currently I am not able to think how they fit in distributed micro-services architecture.

          Reply
  7. Late to the game here, but I prefer to create UUIDs for resources on the client and create them with a POST operation to the desired location /collection/{uuid} – how does this gel with you?

    Cheers

    John

    Reply
    • Yes, it’s possible to design the API such a way. As far as my preferences go, I will not do this. I will never handover the responsibility of creating uuid to client.

      Reply
  8. The RFC that this post was based on has been superseded. Source https://tools.ietf.org/html/rfc2616

    The particular section I want to highlight as a difference is this:

    “The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line. It essentially means that POST request-URI should be of a collection URI.
    POST /questions”

    The equivalent section in new RFC is at https://tools.ietf.org/html/rfc7231

    The meaningful change is: “The POST method requests that the target resource process the representation enclosed in the request according to the resource’s own specific semantics.”

    So essentially POST is less prescriptive on usage.

    I think what this means is that the semantics of POST to create a sub-resource is still a good pattern to follow, it is an example usage even in the new RFC, however, we shouldn’t try to state that POST means create, that’s just one possibility.

    The important points to follow with POST is that if a resource is created then a Location header must be specified and 201 response returned. We can also use hypermedia to describe to clients the behavior of POST.

    GET /resource could return

    
    {
      _links: {
        create: {href: "/resource", method: "post"}
      }
    }
    

    I would say OPTIONS /resource returning GET, POST, OPTIONS is not sufficient information to describe that POSTing will actually create a new resource.

    Apologies for adding complexity to a really clearly laid out blog

    Reply
  9. This is the best post. I have searched this question on many websites but this answers in a single read. Thanks.

    Reply
  10. Very nicely done! The only stickler re idempotency on the PUT example is that many systems will implement some form of IAudit on editing operations, updating a “last edited timestamp” on the resource … in such case, the “update timestamp” for that resource would technically update automatically making the result of the operation not 100% identical (but prob 99.9%). But that does not change the essence of the topic.

    Reply
    • From https://tools.ietf.org/html/rfc7231#page-23:
      Like the definition of safe, the idempotent property only applies to
      what has been requested by the user; a server is free to log each
      request separately, retain a revision control history, or implement
      other non-idempotent side effects for each idempotent request.

      I read this to say timestamps are server added and do not affect the idempotent property.

      Reply

Leave a Comment