POST vs other HTTP request methods (GET, PUT, PATCH) — and why to use them rather than using just POST method for everything

Yoshita Arora
6 min readMay 28, 2019

--

Hola developer! Glad to see you here again!

So, you’ve just recently shifted from a frontend developer to a backend one, and you’ve started coding some basic CRUD APIs.

As a beginner you might probably be handling all your CRUD operations using just one single HTTP request method — POST, and you might be wondering why in the world do other methods exist at all when everything can be done with just this one method easily.

In this article i’ll be giving an answer to this query of yours.

Ready for it? let’s go!

Firstly, let me define all the types of HTTP requests one by one for you and then we’ll get into why its better to use them over just the POST one.

GET :

  • GET is the simplest type of HTTP request method; the one that browsers use each time you click a link or type a URL into the address bar.
  • It instructs the server to transmit the data identified by the URL to the client.
  • You cannot send a “body” in a GET request.
  • Data should never be modified on the server side as a result of a GET request. In this sense, a GET request is read-only.

Example :

GET /user/1
{
“username”: “yoshi123”,
“email”: “yoshi123@example.com
}

POST :

  • The POST method is mostly used to create new resources (or documents).
  • The API receives the data sent by the user inside the “body” of the request.
  • If the Client sends data without any id using the POST method then we will store it and assign a new id.
  • If the Client again sends the same data without any id using the POST method, then we will store it and assign a new id. So basically, duplication is allowed here.

Example :

POST /user/
{
“username”: “yoshi1234”, //new user
“email”: “yoshi1234@example.com
}

PUT :

  • If the Client sends data with an id then we will check whether that id exists.
  • If the id exists we will update the data else we will create a new one and assign it a new id.

Example :

PUT /user/1
{
“username”: “yoshi1234”,
“email”: “yoshi357@gmail.com

// new email address
}

Note here that even if we want to update just the email address, we still need to send the entire payload i.e all the other things also in the body. If other keys are not sent, that data will be lost.

Example:

GET /user/1
{
“username”: “yoshi1234”,
“email”: “yoshi1234@example.com
}
PUT /user/1
{
“email”: “yoshi357@gmail.com

// new email address
}

GET /user/1
{
“email”: “yoshi357@gmail.com

// just email, nothing else
}

PATCH :

  • If the Client sends data with an id then we will check whether that id exists.
  • If the id exists we will update data else we will throw an exception.

Example :

PATCH /user/1
{
“email”: “yoshi357@gmail.com

// new email address
}

  • PATCH can be both idempotent as well as non-indempotent.
  • When Indempotent and you made a change, and you made the same change again and again, it would always give back the same result, i.e, you changed the email address to the new value
  • In more accessible language, an idempotent PATCH could be defined as: After PATCHing a resource with a patch document, all subsequent PATCH calls to the same resource with the same patch document will not change the resource:

GET /user/1
{
“username”: “yoshi1234”,
“email”: “yoshi357@gmail.com
}
PATCH /user/1
{
“email”: “yoshi357@example.com

// new email address
}

GET /user/1
{
“username”: “yoshi1234”,
“email”: “yoshi357@example.com

// email address was changed
}
PATCH /user/1
{
“email”: “yoshi357@example.com

// new email address… again
}

GET /user/1
{
“username”: “yoshi1234”,
“email”: “yoshi357@example.com

// nothing changed since last GET
}

  • Conversely, a non-idempotent operation is one where after PATCHing a resource with a patch document, subsequent PATCH calls to the same resource with the same patch document do change the resource.
  • To illustrate a non-idempotent PATCH, suppose there is a /users resource, and suppose that calling GET /users returns a list of users, currently:

[

{ “id”: 1, “username”: “firstuser”, “email”:“firstuser@example.org” }

]

  • Rather than PATCHing /users/{id}, as in the previous (indempotent) example, suppose the server allows PATCHing /users. Let’s issue this PATCH request:

PATCH /users
[

{ “op”: “add”,

“username”: “newuser”,

“email”: “newuser@example.org” }

]

  • Our patch document instructs the server to add a new user called newuser to the list of users. After calling this the first time, GET /users would return:

[

{ “id”: 1, “username”: “firstuser”, “email”: “firstuser@example.org” },
{ “id”: 2, “username”: “newuser”, “email”: “newuser@example.org” }

]

  • Now, if we issue the exact same PATCH request as above, what happens? (For the sake of this example, let’s assume that the /users resource allows duplicate usernames.) The “op” is “add”, so a new user is added to the list, and a subsequent GET /users returns:

[

{ “id”: 1, “username”: “firstuser”, “email”: “firstuser@example.org” },
{ “id”: 2, “username”: “newuser”, “email”: “newuser@example.org” },
{ “id”: 3, “username”: “newuser”, “email”: “newuser@example.org” }

]

  • The /users resource has changed again, even though we issued the exact same PATCH against the exact same endpoint, hence, this particular PATCH is not idempotent.
  • A PATCH request can be issued in such a way as to be idempotent, which also helps prevent bad outcomes from collisions between two PATCH requests on the same resource in a similar time frame.

Now that you know exactly what these POST, PUT and PATCH terms mean, the question comes as to why use GET, PUT and PATCH for their exact purposes rather than using POST in place of them.

And following are the exact reasons:

  • Semantic difference: the intention of each operation is different, so it helps developers understand the API. Also, it helps the API to be machine-consumable as a software can understand the semantics behind each operation.
  • The main benefits of using the different types of request methods HTTP defines is that it hints at what you are trying to achieve with the request.
  • So if you are making a GET request you are hinting that you want to fetch something (usually without making any changes). If you are making a POST request you are hinting that your request will create some new data etc.
  • These hints (or metadata about your request) can be used by the browser or the server code that handles your request to make some optimizations (or just handle the request differently) even without understanding the content of your request.
  • An example of these types of optimizations is that the browser can cache GET requests and not POST requests.
  • These hints are also useful to humans. If for example I expose the following API in my server:

GET /user/{userId}
POST /user/{userId}
DELETE /user/{userId}

  • Anyone who is familiar with REST will know just by seeing this (the above routes) that calling this url with GET will fetch the requested user, POST will create a new user and DELETE will delete the user.
  • It makes routes more concise, and is a fundimental in creating RESTful API’s. For example, I have routes for blog articles, these routes implement basic CRUD functionality (Create, Read, Update, Delete) with the following routes:

[POST] /api/article | Creates an article
[GET] /api/article | Lists articles
[GET] /api/article/:id | Gets an article by ID
[PUT] /api/article/:id | Updates and article by ID
[DELETE] /api/article/:id | Deletes article by ID
[DELETE] /api/article | Bulk delete articles

  • So in the above example I only actually have 2 routes “/api/article” and “/api/article/:id”. But I use 4 different HTTP methods to access them.
  • If I were to just use POST, then I’d have 6 different routes, and if I wanted to articulate that later on I could end up with a big heaping mess of routes, and other developers would not want to work with me.

Also, some differences between POST and GET request are as follows:

GET :

  • GET requests can be cached
  • GET requests remain in the browser history
  • GET requests can be bookmarked
  • GET requests should never be used when dealing with sensitive data
  • GET requests have length restrictions
  • GET requests should be used only to retrieve data

POST :

  • POST requests are never cached
  • POST requests do not remain in the browser history
  • POST requests cannot be bookmarked
  • POST requests have no restrictions on data length.

That’s all for this article.

I hope you found this article helpful, and I wish to see you again somewhere here sometime later but sooner ;)

Till then, keep sipping that coffee of yours and keep Coding!

Happy Coding! :)

--

--