Multi-tenancy
One Query Language for Four Database Engines
Your application uses PostgreSQL, MongoDB, MySQL, and Redis. Each has its own query syntax. OmniQL lets you write one query and execute it against any of them.
The multi-engine problem
Modern SaaS applications rarely use a single database. Relational data goes to PostgreSQL or MySQL. Documents go to MongoDB. Caching and sessions go to Redis. Each engine is chosen for what it does best.
The cost of this flexibility is four different query languages. SQL for PostgreSQL. SQL with different syntax for MySQL. MQL (MongoDB Query Language) for MongoDB. Redis commands for Redis. Each has its own syntax, its own conventions, its own edge cases.
For a single-database application, this is not a problem. You learn one query language and use it everywhere. For a multi-engine application, your team must be fluent in multiple query languages. Your codebase contains different query patterns for different engines. Your tooling, testing, and debugging workflows are fragmented.
When you add multi-tenancy to this equation, the complexity multiplies. Every query must be scoped to the correct tenant. Every engine needs its own tenant-aware middleware. Every operation, whether it is a simple read or a schema change, has a different syntax depending on which engine it targets.
What OmniQL does
OmniQL is a unified query language that compiles to the native syntax of each database engine. You write one query. The proxy translates it to PostgreSQL SQL, MySQL SQL, MongoDB MQL, or Redis commands depending on which engine the tenant's database runs on.
This single query compiles to:
The query is written once. The proxy handles the translation. Your application code does not need to know which engine the tenant uses.
Why this matters for multi-tenant applications
In a multi-tenant platform, different tenants might use different database engines. One tenant's workspace might be PostgreSQL. Another might be MongoDB. A third might use both.
Without a unified query language, your application needs conditional logic per engine:
With OmniQL, the same operation is one line regardless of the engine:
The proxy resolves which engine the tenant uses and compiles the query to the correct syntax. The application never deals with engine-specific logic.
CRUD operations
OmniQL covers the standard create, read, update, and delete operations with a consistent syntax across all engines.
Create:
Compiles to INSERT INTO (PostgreSQL/MySQL), db.collection.insertOne (MongoDB), or HSET (Redis).
Read:
Compiles to SELECT (PostgreSQL/MySQL), db.collection.find (MongoDB), or key-based retrieval (Redis).
Update:
Compiles to UPDATE (PostgreSQL/MySQL), db.collection.updateMany (MongoDB), or HSET (Redis).
Delete:
Compiles to DELETE FROM (PostgreSQL/MySQL), db.collection.deleteMany (MongoDB), or DEL (Redis).
The syntax is intentionally simple. It covers the operations that are common across all four engines. For engine-specific features that do not translate (PostgreSQL CTEs, MongoDB aggregation pipelines, Redis sorted sets), you can always use native queries through the proxy.
Filtering and expressions
OmniQL supports the standard comparison and logical operators:
Each expression compiles to the native equivalent. LIKE becomes a regex in MongoDB. IS NULL becomes a $exists check. IN becomes $in. The translation handles the differences so the query author does not have to.
Aggregations
OmniQL supports common aggregation functions:
These compile to SQL aggregate functions (PostgreSQL/MySQL), MongoDB aggregation pipeline stages, or Redis-specific computation depending on the engine.
When to use OmniQL vs native queries
OmniQL is designed for operations that are common across all engines. For the majority of application queries (CRUD, filtering, basic aggregations), it eliminates the need for engine-specific code.
There are cases where native queries are the right choice:
Complex PostgreSQL queries with CTEs, window functions, or advanced JOIN patterns do not have equivalents in MongoDB or Redis. Write these as native SQL.
MongoDB aggregation pipelines with $lookup, $unwind, or $graphLookup stages are specific to MongoDB's document model. Write these as native MQL.
Redis data structures like sorted sets, streams, or pub/sub have no relational equivalent. Use native Redis commands.
The proxy accepts both OmniQL and native queries. You can mix them freely within the same application. Use OmniQL for the 80% of queries that are standard CRUD and native queries for the 20% that need engine-specific features.
Both OmniQL and native queries go through the same proxy, the same tenant isolation, the same query logging, and the same settings enforcement.
Cross-tenant queries
OmniQL works with the admin query endpoint, which can execute the same query across all tenants simultaneously:
One query, executed against every tenant's database, results aggregated per tenant. The proxy compiles the OmniQL to the correct syntax for each tenant's engine and runs them in parallel.
Schema operations
OmniQL also supports schema operations that work across engines:
These compile to CREATE TABLE (PostgreSQL/MySQL), implicit collection creation with validators (MongoDB), or key structure conventions (Redis). Schema operations through OmniQL are tracked by the blueprint versioning system and can be deployed to all tenants.
The practical benefit
OmniQL does not replace deep knowledge of individual database engines. Your team still needs to understand PostgreSQL's indexing strategies, MongoDB's document model, and Redis's data structures.
What it eliminates is the boilerplate. The conditional code paths per engine. The syntax differences between INSERT INTO and db.collection.insertOne. The different ways four engines represent the same logical operation.
For a multi-tenant application that supports multiple database engines, this boilerplate adds up. Every CRUD endpoint has engine-specific branches. Every test suite has engine-specific assertions. Every new developer on the team must learn multiple query languages before they can be productive.
OmniQL reduces this to one syntax for the common operations and native queries for the rest. The proxy handles the translation. The application code stays clean.
Getting started
OmniQL is built into the TenantsDB proxy. Every query that passes through the proxy can be OmniQL or native. There is nothing to install, configure, or enable.
OmniQL works in workspaces, tenant queries, and admin queries. The same syntax, everywhere.
Start free with up to 5 tenants at docs.tenantsdb.com.