---
title: "Introducing Conditional REST Requests"
description: "Introducing Conditional REST Requests"
published: "2017-07-31"
last_updated: "2017-07-31"
authors:
  - "Casey Rogers (Software Engineer)"
categories:
  - "Realtime Database"
  - "Launch"
canonical_url: "https://firebase.blog/posts/2017/07/introducing-conditional-rest-requests"
---

# Introducing Conditional REST Requests

*Published July 31, 2017 by Casey Rogers (Software Engineer)*

---
REST users rejoice! Conditional requests are here!  

How would you increment an integer in the Realtime Database? It's not always as easy as just grabbing a value, adding one, and writing it back again. When multiple users are simultaneously reading, updating and writing the same value, some users' writes could get "lost" due to race conditions.  

Let's say you're using the Realtime Database to store upvotes on videos, and two of your users want to upvote the "Silly Cat Video" which currently stands at ten upvotes. Each user reads the value '10' from the database. They then independently increment the value locally and write '11' back to the database. "Silly Cat Video" now only has eleven upvotes when it should have twelve.  

How do we prevent this? On a mobile or web client, you could use [transactions](https://firebase.google.com/docs/database/web/read-and-write#save_data_as_transactionshttps://firebase.google.com/docs/database/web/read-and-write#save_data_as_transactions), which have long been supported in our realtime SDKs. But what if you're using the REST API?  

Good news for you: we've just added conditional requests to the REST API! While conditional requests work differently than the realtime transactions, we can still use them to safely perform atomic operations.  

### How to increment requests  

#### Step 1: Request Data and ETag 

Request:  

```bash
# -i returns headers in the response, -H sets a header
curl -i 
-H 'X-Firebase-ETag: true' 
'https://<your-database>.firebaseio.com/videos/silly_cat_video/upvotes.json'
```

Response:  

```js
HTTP/1.1 200 OK
...
ETag: ViJFJowpbyRvgGNPzPJdGeN+mCY=
...

10  // Value at the specified location
```

#### Step 2: Write the New Value

Request:

```bash
# -X sets the method (defaults to GET), -d provides data to the method
curl -i 
-X PUT 
-d '11' 
-H 'if-match: ViJFJowpbyRvgGNPzPJdGeN+mCY=' 
'https://<your-database>.firebaseio.com/videos/silly_cat_video/upvotes.json' 
```

If no other users have incremented `upvotes.json` the PUT request will succeed. If another user has, the request will fail and the response will contain the new ETag and data. Use these to calculate a new upvotes value and retry the PUT request.  

But wait, what does all this `ETag` and `if-match` stuff mean, and how do they work?  

The Realtime Database's conditional REST requests use [`ETags`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) and the [`if-match`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-Match) header from the [HTTP conditional requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests) standard. An `ETag` is a short unique identifier for data at a location: if the data changes, so does its `ETag`. `if-match`, when set to an `ETag` value, tells the database to only complete a request's operation if the data the request would overwrite matches the provided `ETag`.  
Together, these two features enable a [Compare and Swap](https://en.wikipedia.org/wiki/Compare-and-swap) (CAS) paradigm. Compare and Swap uses the two step process we saw in our video upvote example:  

1. Fetch the location you wish to update along with its `ETag`.

2. Issue a PUT request with new data in the body and the `ETag` of the old data in the `if-match` header.  
If the data at the location changes between Step 1 and Step 2, the database will not complete the operation and will return an error containing the new `ETag` and data. You can use these values to construct a new PUT request and retry from Step 2.  

For more details and to get started check out our [REST conditional requests guide](https://firebase.google.com/docs/database/rest/save-data#section-conditional-requests).
