- How to connect Node.js to Redis.
- Basic Redis commands (set, get, delete).
- A simple example to test everything.
Before coding, ensure your Redis Docker container is running (from the previous steps). Open PowerShell and run:
docker ps
If you see my-redis
, you’re ready!
-
Open a folder (e.g.,
redis-demo
) and initialize a Node.js project:npm init -y
-
Install the Redis client library (we’ll use
ioredis
):npm install ioredis
Create a file app.js
and add this code to connect to Redis:
// Import the Redis library
const Redis = require("ioredis");
// Create a connection to Redis (running in Docker)
const redis = new Redis({
host: "localhost", // Docker's default IP
port: 6379, // Redis port
});
// Test the connection
async function testConnection() {
try {
const reply = await redis.ping();
console.log("Redis says:", reply); // Should print "PONG"
} catch (err) {
console.error("Failed to connect to Redis:", err);
}
}
testConnection();
Run it with:
node app.js
If you see Redis says: PONG
, it works! 🎉
Let’s learn 3 essential commands: SET, GET, and DEL.
async function setKey() {
await redis.set("message", "Hello from Node.js!");
console.log("Data saved!");
}
setKey();
async function getKey() {
const value = await redis.get("message");
console.log("Value:", value); // Prints "Hello from Node.js!"
}
getKey();
async function delKey() {
await redis.del("message");
console.log("Key deleted!");
}
delKey();
Update app.js
with this code to test all steps together:
const Redis = require("ioredis");
const redis = new Redis({ host: "localhost", port: 6379 });
async function main() {
// 1. Test connection
console.log(await redis.ping()); // Should print "PONG"
// 2. Save data
await redis.set("fruit", "apple");
console.log("Saved: fruit → apple");
// 3. Read data
const fruit = await redis.get("fruit");
console.log("Read:", fruit); // Prints "apple"
// 4. Delete data
await redis.del("fruit");
console.log("Deleted 'fruit'");
}
main()
.then(() => process.exit(0))
.catch((err) => console.error(err));
Run it:
node app.js
You’ll see:
PONG
Saved: fruit → apple
Read: apple
Deleted 'fruit'
- Async/Await: We use
async/await
because Redis operations are asynchronous (they take time). - Simple Data Types: Redis stores data as strings by default. For numbers/objects, use
JSON.stringify()
:await redis.set("user", JSON.stringify({ name: "Alice", age: 30 })); const user = JSON.parse(await redis.get("user"));
- Close the Connection (Optional):
await redis.quit();
Error | Fix |
---|---|
Connection refused |
Ensure Docker and Redis are running (docker ps ). |
ReplyError: ERR no such key |
The key doesn’t exist. Check spelling! |
ECONNREFUSED |
Wrong port/host. Double-check localhost:6379 . |
Let’s explore SETEX
, HSET
, and LPUSH
with simple examples in Node.js! These commands unlock Redis’ power for caching, storing objects, and managing lists.
What it does: Stores a key-value pair that auto-deletes after X seconds.
Use case: Temporary data (e.g., OTP codes, session tokens).
// Store a key "promo_code" with value "SALE20" for 30 seconds
await redis.setex("promo_code", 30, "SALE20");
console.log("Promo code set!");
// Retrieve it before it expires
const promo = await redis.get("promo_code");
console.log(promo); // "SALE20" (if within 30s)
// After 30s, this returns `null`
const expiredPromo = await redis.get("promo_code");
console.log(expiredPromo); // null
What it does: Stores a hash (object) with multiple fields.
Use case: User profiles, product details.
// Store a user object
await redis.hset("user:123", {
name: "Alice",
email: "alice@example.com",
age: 30,
});
console.log("User saved!");
// Retrieve the entire user object
const user = await redis.hgetall("user:123");
console.log(user);
// { name: 'Alice', email: 'alice@example.com', age: '30' }
// Get a single field
const email = await redis.hget("user:123", "email");
console.log(email); // "alice@example.com"
What it does: Pushes items to the beginning of a list.
Use case: Activity logs, task queues, recent items.
// Add tasks to a list
await redis.lpush("tasks", "Buy milk");
await redis.lpush("tasks", "Call mom");
console.log("Tasks added!");
// Get all tasks (0 = start, -1 = end)
const tasks = await redis.lrange("tasks", 0, -1);
console.log(tasks); // ["Call mom", "Buy milk"]
// Get the first task (leftmost item)
const firstTask = await redis.lindex("tasks", 0);
console.log(firstTask); // "Call mom"
const Redis = require("ioredis");
const redis = new Redis({ host: "localhost", port: 6379 });
async function main() {
// 1. SETEX: Temporary promo code
await redis.setex("promo:2024", 60, "CG50");
// 2. HSET: User profile
await redis.hset("user:456", {
name: "Dev",
role: "developer",
});
// 3. LPUSH: Recent activities
await redis.lpush("activity:456", "Logged in");
await redis.lpush("activity:456", "Updated profile");
// Retrieve data
const promoCode = await redis.get("promo:2024");
const user = await redis.hgetall("user:456");
const activities = await redis.lrange("activity:456", 0, -1);
console.log({ promoCode, user, activities });
}
main().catch(console.error);
Output (if run within 60 seconds):
{
promoCode: 'CG50',
user: { name: 'Dev', role: 'developer' },
activities: [ 'Updated profile', 'Logged in' ]
}
Command | Description | Example |
---|---|---|
SETEX |
Set key-value with expiration | await redis.setex("key", 30, "value") |
HSET |
Store an object (hash) | await redis.hset("user:1", { name: "Alice" }) |
HGETALL |
Get entire hash | await redis.hgetall("user:1") |
LPUSH |
Add to a list (left side) | await redis.lpush("tasks", "task1") |
LRANGE |
Get list items | await redis.lrange("tasks", 0, -1) |
- Run the examples above in your
app.js
file. - Modify the keys/values (e.g., change
user:123
toproduct:789
). - Use
redis-cli
to check data manually:Then run commands like:docker exec -it my-redis redis-cli
GET promo:2024 HGETALL user:456 LRANGE activity:456 0 -1
SETEX
: Temporary sessions, OTP codes, flash sales.HSET
: User profiles, configurations, product details.LPUSH
: Activity feeds, task queues, recent searches.
Let’s build a simple API caching system using Redis in Node.js. This will speed up your app by storing responses from slow/downstream APIs and serving them instantly on subsequent requests.
- User requests data (e.g.,
/posts/1
). - Check if data is cached in Redis.
- Yes: Return cached data immediately.
- No: Fetch from the API, store it in Redis, then return it.
- Install required packages:
npm install express axios ioredis
- Create
app.js
and add this code:
const express = require("express");
const axios = require("axios");
const Redis = require("ioredis");
const app = express();
const redis = new Redis({ host: "localhost", port: 6379 }); // Redis Docker container
const PORT = 3000;
// Example API to cache (we'll use JSONPlaceholder)
const API_URL = "https://jsonplaceholder.typicode.com/posts";
// Cache middleware
async function cacheMiddleware(req, res, next) {
const { id } = req.params;
const cacheKey = `post:${id}`;
try {
// Check Redis for cached data
const cachedData = await redis.get(cacheKey);
if (cachedData) {
console.log("Serving from cache 🚀");
return res.send(JSON.parse(cachedData));
}
next(); // No cache → proceed to fetch
} catch (err) {
console.error("Cache error:", err);
next();
}
}
// Route: Get a post by ID (with caching)
app.get("/posts/:id", cacheMiddleware, async (req, res) => {
const { id } = req.params;
const cacheKey = `post:${id}`;
try {
// Fetch from API
const response = await axios.get(`${API_URL}/${id}`);
const data = response.data;
// Save to Redis (expire after 1 hour = 3600 seconds)
await redis.setex(cacheKey, 3600, JSON.stringify(data));
console.log("Serving from API ⚡");
res.send(data);
} catch (err) {
res.status(500).send("Error fetching post");
}
});
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
- Start the server:
node app.js
- Open your browser or use
curl
:curl http://localhost:3000/posts/1
- First request: Fetches from API, saves to Redis.
- Second request: Returns cached data instantly!
Code Part | Purpose |
---|---|
cacheMiddleware |
Checks Redis for cached data before hitting the API. |
redis.setex |
Stores data with expiration (1 hour here). |
JSON.parse /JSON.stringify |
Converts data to/from strings (Redis only stores strings). |
axios |
Fetches data from the external API. |
First Request (API):
Serving from API ⚡
{
"userId": 1,
"id": 1,
"title": "sunt aut...",
"body": "quia et suscipit..."
}
Second Request (Cache):
Serving from cache 🚀
{
"userId": 1,
"id": 1,
"title": "sunt aut...",
"body": "quia et suscipit..."
}
- Faster Responses: Cached data avoids slow API calls.
- Reduced Load: Fewer requests to the external API.
- TTL (Time-To-Live): Auto-deletes stale data with
setex
.
- Cache Invalidation: Delete keys when data changes:
app.delete("/posts/:id", async (req, res) => { const { id } = req.params; await redis.del(`post:${id}`); res.send("Cache invalidated"); });
- Cache All Posts: Modify the middleware to cache list endpoints.
- Error Handling: Add retries if Redis/API fails.
- Cache weather data, stock prices, or news feeds.
- Store results of expensive database queries.
- Speed up e-commerce product listings.