The Pain of Forcing Redis to Be Your Primary Database
For a long time, developers have defaulted to using Redis only for caching—storing a string, incrementing a counter, or at most, managing simple Hashes. However, as projects grow, you often need to store more complex data, such as user profiles with various nested addresses and interests. This is where using raw Redis starts to reveal its limitations.
If you insist on using Redis Core for these cases, you usually fall into two traps:
- Trap 1: Forcing the entire Object into a JSON string and tossing it into a single Key. Every time you want to update a name or phone number, you have to fetch the whole JSON blob, parse it, modify it, and push it back. This operation is extremely CPU and bandwidth-intensive if the object is several MBs.
- Trap 2: Splitting it into Hashes. This method is fast but leaves you blind when it comes to searchability. You cannot ask Redis: “Filter the list of customers in HCM City who have spent over 5 million” using only basic commands like
SCAN.
Redis OM (Object Mapping) emerged to solve this problem. Think of it as Mongoose for MongoDB or SQLAlchemy for SQL, but running on the blazing-fast foundation of RedisJSON and RediSearch.
Why is Redis OM Worth Using?
Instead of writing clunky code, Redis OM allows you to define clear Models (Schemas). It transforms complex Redis commands into extremely readable, object-oriented methods.
The key selling points include:
- Automatic indexing for lightning-fast Full-text search.
- Direct queries into nested structures without fetching the entire Object.
- Significant development time savings (reducing boilerplate code by about 30-50% compared to using raw drivers).
- Comprehensive support for both Python and Node.js.
Setting Up a Proper Environment
To use Redis OM, standard Redis isn’t enough. You need Redis Stack — the “full option” version that comes integrated with search and JSON processing modules.
The fastest way to deploy is via Docker with a single command:
docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:latest
After running it, open localhost:8001. The Redis Insight interface here will help you visualize your data instead of typing terminal commands until your hands get tired.
Hands-on with Python (Redis-om-python)
First, install the library using pip:
pip install redis-om
Let’s try building an HR management system. We need to store personal information and bios for searching. The Model definition is very similar to Pydantic:
from redis_om import HashModel, Field, Migrator
from typing import Optional
from pydantic import EmailStr
class Employee(HashModel):
name: str = Field(index=True)
email: EmailStr = Field(index=True)
age: int = Field(index=True)
bio: str = Field(index=True, full_text_search=True)
city: str = Field(index=True)
# The most important step: Create the index
Migrator().run()
Don’t forget the Migrator().run() command. Without it, Redis won’t know how to search your data, and all returned results will be a big fat zero.
Adding data and performing a complex query:
# Save a new employee
emp = Employee(name="Hoang Anh", email="[email protected]", age=30, bio="Backend expert with 5 years of experience", city="Hanoi")
emp.save()
# Find people in Hanoi over 25 years old
results = Employee.find((Employee.city == "Hanoi") & (Employee.age > 25)).all()
Implementation with Node.js (Redis-om-node)
For Node.js developers, the syntax is even smoother with Async/Await.
npm install redis-om
Here is how you set up a Schema and search for products in stock:
import { Client, Entity, Schema } from 'redis-om';
const client = new Client();
await client.open('redis://localhost:6379');
class Product extends Entity {}
const productSchema = new Schema(Product, {
name: { type: 'string', indexed: true },
description: { type: 'string', textSearch: true },
price: { type: 'number', indexed: true }
});
const repo = client.fetchRepository(productSchema);
await repo.createIndex();
// Find laptops under $2000 with a description containing "thin and light"
const products = await repo.search()
.where('description').matches('thin and light')
.and('price').is.lessThan(2000)
.return.all();
Handling Nested Objects
This is Redis OM’s secret weapon. In reality, data often has a complex tree structure. For example: An order contains multiple products, and each product has its own category.
If you need to quickly convert data from CSV to JSON to test this nested structure, use the tool at toolcraft.app/en/tools/data/csv-to-json. This tool processes right in the browser, so your data remains secure.
To store nested data, switch from HashModel to JsonModel:
from redis_om import JsonModel
from typing import List
class Address(JsonModel):
street: str
zip_code: str
class Customer(JsonModel):
name: str = Field(index=True)
addresses: List[Address] # Extremely flexible nested structure
Thanks to RedisJSON, you can query deep into every corner of the Object while maintaining sub-millisecond speeds.
Practical Experience from Projects
After deploying Redis OM for systems handling thousands of requests per second, I have a few notes for you:
- RAM Management: Full-text search is great, but it’s extremely RAM-intensive. Only enable
textSearch: truefor fields that truly need it, like product descriptions or user bios. - Data Constraints: Redis OM is very strict. If a Model is defined as
intbut you pass astring, the app will crash immediately. Control your input data carefully. - JSON Depth: Although nested structures are supported, don’t overdo it beyond 3-4 levels. The flatter the structure, the more stable the query performance.
- Index: Always run the index creation command whenever you deploy a new version with Schema changes.
Summary
Redis OM has taken Redis to a new level; it’s no longer just a temporary storage layer. If you need a database with extremely fast response times, flexible search support, and a modern JSON structure, this is the number one choice.
Of course, for complex relational data, SQL still has its place. But for problems requiring speed and flexibility, the Redis Stack + Redis OM combo is a formidable contender in your arsenal.

