Mastering INCR and DECR: Atomic Counters in Redis
Learn how to use Redis INCR and DECR commands to build thread-safe counters. Avoid race conditions and master atomic operations for your API backends.

Previously in this course, we explored the Introduction to Atomic Operations: Redis Performance & Integrity, where we established why Redis is inherently safe for single-command operations. In this lesson, we add practical power to that concept by learning how to manipulate integers using specialized commands.
When you need to count things—like API requests, page views, or inventory stock—you often encounter the "read-modify-write" problem. If two users click a button at the exact same time, a traditional database might read the value "10," both increment it in their local application memory to "11," and write "11" back to the database. The result? You missed one click.
Redis solves this with atomic INCR and DECR commands.
Understanding Atomic Increments and Decrements
Redis stores string values that represent integers as special internal structures. Because Redis is single-threaded, when you run INCR, it performs the entire operation—fetching the value, adding one, and saving it back—as a single, uninterrupted unit of work.
The Core Commands
INCR key: Increments the integer value of a key by one. If the key does not exist, it is set to 0 before performing the operation.DECR key: Decrements the integer value of a key by one.INCRBY key increment: Increases the value by a specific integer amount.DECRBY key decrement: Decreases the value by a specific integer amount.
Worked Example: Tracking API Requests

In our project, we need to track how many requests a specific user makes. Using INCR is the standard way to implement a basic counter for this purpose.
Using the CLI
Open your terminal and connect to your Redis instance:
Bash# Start the count 127.0.0.1:6379> INCR user:101:request_count (integer) 1 # Increment again 127.0.0.1:6379> INCR user:101:request_count (integer) 2 # Decrement after a successful process 127.0.0.1:6379> DECR user:101:request_count (integer) 1
Implementing in Node.js
Using the redis client established in our Setting Up the Backend Project Baseline with Node.js and Redis, here is how you would increment a counter within your API service:
JAVASCRIPTconst client = require(CE9178">'./redisClient'); // Assume this is your configured client async function trackRequest(userId) { const key = CE9178">`user:${userId}:requests`; // Atomically increment the counter const currentCount = await client.incr(key); console.log(CE9178">`User ${userId} has made ${currentCount} requests.`); return currentCount; }
Resetting Counters
Sometimes you need to reset a counter—perhaps when a new time window begins. Since there is no specific RESET command, you simply use DEL or SET the key to 0.
Bash# Resetting the counter 127.0.0.1:6379> DEL user:101:request_count (integer) 1 # The next INCR will start from 1 again
Hands-on Exercise
- Open your
redis-cli. - Create a key named
app:global_counterand increment it three times. - Use
INCRBYto add 5 to that same key. - Use
DECRBYto subtract 2. - Verify the final value is 6.
- Delete the key to reset the state.
Common Pitfalls
- Non-integer values: If you try to run
INCRon a key that stores a string like "hello", Redis will return an error (ERR value is not an integer or out of range). Always ensure your counters are initialized as integers. - Forgetting to handle expiration: Counters often accumulate indefinitely. In our next lessons, we will combine these counters with TTLs to prevent memory bloat.
- Overflow: Redis integers are 64-bit signed integers. While hitting the limit is rare, be aware that you cannot exceed the range of a 64-bit signed integer.
FAQ
Q: What happens if I use INCR on a non-existent key? A: Redis automatically creates the key, treats the initial value as 0, and returns 1.
Q: Are these operations really safe? A: Yes. Because Redis executes commands atomically, no other command can run between the read and the write, effectively eliminating race conditions.
Q: Can I increment by floats?
A: Use INCRBYFLOAT if you need to increment by decimal values.
Recap

We’ve mastered the art of atomic state management. By using INCR and DECR, we ensure our counters remain accurate even under heavy concurrent load. These commands are the building blocks for the rate-limiting and metrics tracking we will implement later in this course.
Up next: Preventing Race Conditions where we will look at how to handle more complex logic safely using transactions.
Work with me

FilamentPHP Admin Panel & Dashboard Development
A powerful admin panel for your Laravel app — built with FilamentPHP so you can manage everything without touching the database.

Laravel REST API Development
Clean, secure, well-documented Laravel REST APIs — the backend engine for your app, mobile client, or SaaS. Built by an API specialist.


