Indexing & Caching in Mindbricks
How Mindbricks makes reads fast (and safe) across DB, Elasticsearch, and Redis.
1. Overview
Mindbricks is designed to generate production-ready microservices, which includes:
-
Efficient database indexing
-
Fast searching & filtering via Elasticsearch
-
Smart caching of entities and queries using Redis
-
Consistent uniqueness constraints across properties and composite keys
The goal is:
You describe what should be indexed or cached via patterns; Mindbricks generates the how in code and infrastructure.
Core patterns involved:
-
PropertyIndexSettings– per-property indexing hints. -
CompositeIndex– multi-field (composite) database index definitions. -
RedisEntityCacheSettings&RedisEntityCacheConfig– per-object caching strategy. -
List/search helpers (
ListSearchFilter,ListOptions) that sit on top of ES and indexing. -
Uniqueness & secondary keys.
Runtime helpers from common such as EntityCache, ElasticIndexer, QueryCache, etc., use these patterns.
2. Property-Level Indexing: PropertyIndexSettings
Every DataProperty may include indexSettings that tell Mindbricks how to index it.
"PropertyIndexSettings": {
"indexedInElastic": "Boolean",
"fulltextSearch": "Boolean",
"indexedInDb": "Boolean",
"unique": "Boolean",
"clusterInRedis": "Boolean",
"cacheSelect": "Boolean",
"isSecondaryKey": "Boolean"
}
2.1 indexedInDb – Database Index
If indexedInDb = true:
-
Mindbricks generates a database index (e.g., in PostgreSQL) for this property.
-
Useful for fields frequently used in
WHERE,ORDER BY, or join conditions.
Example:
"indexSettings": {
"indexedInDb": true
}
Use for:
-
email -
createdAt -
status
2.2 unique – Uniqueness Constraint
If unique = true:
-
A unique index is created on this column.
-
DB-level constraint ensures no two records share the same value.
Example:
"indexSettings": {
"indexedInDb": true,
"unique": true
}
Use for:
-
user.email -
tenant.codename -
apiKey
Note: For uniqueness across multiple fields, use CompositeIndex instead of unique (see below).
2.3 isSecondaryKey – Alternate Identifier
isSecondaryKey = true marks a property as a secondary key:
-
Semantically: “another way to identify a record apart from its primary key (id).”
-
Used by code generators to treat this field as a valid identifier for certain operations.
Example:
-
usernameas secondary key toid -
slugorcodeused as human-friendly ID
"indexSettings": {
"indexedInDb": true,
"isSecondaryKey": true
}
3. Composite Indexes: CompositeIndex & OnDuplicate
Sometimes you need an index over multiple fields (compound index), both for performance and uniqueness.
Pattern:
"CompositeIndex": {
"indexName": "String",
"indexFields": ["PropRefer"],
"onDuplicate": "OnDuplicate"
}
indexFields: list of property references forming the composite index.
OnDuplicate controls how duplicates are handled in insert operations when there’s a unique composite index:
"OnDuplicate": ["doUpdate", "throwError", "stopOperation", "doInsert"]
-
doUpdate– upsert behavior: update existing record when conflict occurs. -
throwError– default DB error on duplicate. -
stopOperation– no error, no insert (silently skip). -
doInsert– ignore uniqueness constraint and insert anyway (index for search only).
3.1 Example – Unique per Tenant
A classic pattern:
email must be unique per tenant.
Define a composite index on (tenantId, email):
"compositeIndexSettings": [
{
"indexName": "uniqueTenantEmailIndex",
"indexFields": ["tenantId", "email"],
"onDuplicate": "throwError"
}
]
Now:
-
user.emailcan repeat across tenants. -
(tenantId, email)pair must be unique.
3.2 Example – Upsert by Composite Key
For a “settings” object:
"compositeIndexSettings": [
{
"indexName": "uniqueSettingPerUser",
"indexFields": ["userId", "settingKey"],
"onDuplicate": "doUpdate"
}
]
Insert operations on the same (userId, settingKey) will update existing records instead of creating duplicates.
4. Elasticsearch Indexing & Full Text Search
Mindbricks supports indexing DataObject instances into Elasticsearch as part of its CQRS/read side. Per property, two flags control ES behavior:
-
indexedInElastic -
fulltextSearch
Also, text-type fields have built-in full text support in ES.
4.1 indexedInElastic
If indexedInElastic = true:
-
This property will be included in the Elasticsearch index for the DataObject.
-
It can be used in filtering, sorting, aggregations, and search.
Example:
"indexSettings": {
"indexedInElastic": true
}
Useful for:
-
status,categoryId, dates, numeric fields, etc. -
Filters in
ListSearchFilterorFetchFromElasticAction.
4.2 fulltextSearch
If fulltextSearch = true:
-
Mindbricks creates an additional text index on this property in ES.
-
Typically used for
String/Textfields where full text search is needed.
Example:
"indexSettings": {
"indexedInElastic": true,
"fulltextSearch": true
}
Notes from the pattern:
Text-type data properties already have full text search, and fulltextSearch adds more explicit index support for non-Text types.
4.3 Using ES in List/Search APIs
Mindbricks uses ES indexes in:
-
ListSearchFilter– pre-search by keyword onsearchProperties, gets ID list, then filters DB query. -
FetchFromElasticAction– raw ES body queries for advanced custom logic. -
BFF DataViews – stored views for complex multi-object read models.
Example ListSearchFilter:
"listOptions": {
"searchFilter": {
"hasSearchFilter": true,
"condition": "!!this.keyword",
"keyword": "this.keyword",
"searchProperties": ["title", "description"]
}
}
Mindbricks:
-
Performs ES search on those properties.
-
Gets matching IDs.
-
Restricts DB list query using
id IN [idsFromES].
5. Redis Entity Caching: RedisEntityCacheSettings
To reduce DB load for frequently-accessed entities, Mindbricks supports entity-level caching in Redis.
Pattern:
"RedisEntityCacheSettings": {
"useEntityCaching": "Boolean",
"configuration": "RedisEntityCacheConfig"
}
"RedisEntityCacheConfig": {
"useSmartCaching": "Boolean",
"cacheCriteria": "MScript",
"checkCriteriaOnlyInCreateAndUpdates": "Boolean"
}
5.1 useEntityCaching
If useEntityCaching = true:
-
Each entity instance of this DataObject may be cached in Redis.
-
Reads can first check the Redis EntityCache.
-
Updates/deletes will invalidate or refresh the cached entries.
5.2 cacheCriteria (MScript)
This optional MScript expression decides which instances should be cached:
Example:
"cacheCriteria": "{ isActive: { "$eq": true }, status: { "$eq": 'published' } }"
Only objects matching this query are cached.
cacheCriteria is usually an MScript Query object; Mindbricks uses it to decide cache eligibility at create/update or at read time (depending on config).
5.3 useSmartCaching
If useSmartCaching = true:
-
TTL (time-to-live) for cache entries can be adjusted based on access frequency or other heuristics.
-
Good for large datasets with irregular access patterns (hot vs cold entities).
5.4 checkCriteriaOnlyInCreateAndUpdates
-
true→ EvaluatecacheCriteriaonly during create/update.- Good when criteria depend only on entity fields (e.g.,
isActive,status).
- Good when criteria depend only on entity fields (e.g.,
-
false→ Re-evaluate at read time.- Good when criteria depend on external context such as current date/time.
5.5 Runtime Helpers
The generated code uses the EntityCache helper from common:
-
EntityCache.get(...)– check Redis for a cached entity. -
EntityCache.set(...)– store entity in Redis. -
EntityCache.invalidate(...)– on updates/deletes.
This logic is integrated into Business APIs where readFromEntityCache is enabled (e.g., ApiOptions.readFromEntityCache = true for certain get or list APIs).
6. Property-Level Caching Hints: clusterInRedis & cacheSelect
Back in PropertyIndexSettings, we saw:
-
clusterInRedis -
cacheSelect
These are hints for how Redis should be used around this property.
6.1 clusterInRedis
“Specifies whether the property should contribute to Redis cluster keys for partial cache invalidation.”
-
When
clusterInRedis = true, this field is used to group cache entries. -
This helps implement targeted invalidation: e.g., “invalidate all cached entities with
tenantId = X” or “all events forprojectId = Y”.
Example:
"indexSettings": {
"clusterInRedis": true
}
Use for:
-
tenantId(clientId,storeId, etc.) -
projectId,organizationIdwhen many rows group under a parent
6.2 cacheSelect
“Defines whether this property is used as a key in Redis entity cache for batch-select operations.”
-
cacheSelect = truemeans developers may use this property as a lookup key in cached sets. -
E.g., caching an ID list of entities by
status.
Example:
"indexSettings": {
"cacheSelect": true
}
Use for:
statusortypefields when you frequently need “all objects matching this status” from cache.
These hints affect how the generated code (or your custom library code) uses EntityCache, QueryCache, and cluster strategies.
7. Query-Level Caching (Runtime Helpers)
Beyond entity caching, Mindbricks common library provides:
-
QueryCache -
QueryCacheInvalidator
These are runtime abstractions for caching expensive queries:
-
Map a query signature (e.g., JSON representation + version) to a cached result.
-
Provide invalidation hooks when underlying data changes.
While not configured via patterns yet, they work on top of DB and ES indexing and per-object entity caching.
Example conceptual use pattern (in service library):
const { QueryCache, QueryCacheInvalidator } = require("common");
const queryCache = new QueryCache("userList");
async function getExpensiveUserList(criteria) {
const key = JSON.stringify(criteria);
const cached = await queryCache.get(key);
if (cached) return cached;
const result = await DB.getUserListByQuery(criteria);
await queryCache.set(key, result);
return result;
}
8. Putting It All Together – Example Design
Imagine a multi-tenant SaaS with Event objects.
8.1 Data Property Index Settings
For the Event DataObject:
"properties": [
{
"basicSettings": { "name": "tenantId", "type": "ID" },
"indexSettings": {
"indexedInDb": true,
"clusterInRedis": true
}
},
{
"basicSettings": { "name": "title", "type": "String" },
"indexSettings": {
"indexedInElastic": true,
"fulltextSearch": true
}
},
{
"basicSettings": { "name": "code", "type": "String" },
"indexSettings": {
"indexedInDb": true,
"unique": true,
"isSecondaryKey": true
}
},
{
"basicSettings": { "name": "startDate", "type": "Date" },
"indexSettings": {
"indexedInDb": true,
"indexedInElastic": true
}
}
]
8.2 Composite Index
"compositeIndexSettings": [
{
"indexName": "tenantStartDateIndex",
"indexFields": ["tenantId", "startDate"],
"onDuplicate": "doInsert"
}
]
Used for fast tenant-scoped event queries.
8.3 Redis Entity Cache
"objectSettings": {
"redisEntityCacheSettings": {
"useEntityCaching": true,
"configuration": {
"useSmartCaching": true,
"cacheCriteria": "{ isActive: { "$eq": true } }",
"checkCriteriaOnlyInCreateAndUpdates": true
}
}
}
Now:
-
Active events are cached.
-
TTL is dynamically computed.
-
tenantIdhelps cluster invalidation.
8.4 List/Search Business API
-
Use
searchFilterontitle. -
Use
listSortByonstartDate. -
Use
membershipFilters&permissionFiltersfor access. -
Use BFF DataView + ES for advanced multi-index dashboards.
9. Summary
Indexing and caching in Mindbricks are pattern-driven and deeply integrated:
-
Property-level index hints (
indexedInDb,indexedInElastic,fulltextSearch,unique,isSecondaryKey,clusterInRedis,cacheSelect)- Control how DB, Elasticsearch, and Redis treat each property.
-
CompositeIndex &
OnDuplicate- Support complex unique constraints and upsert-like behavior.
-
Elasticsearch integration
-
Per-property ES indexing and full-text search.
-
Higher-level features like
ListSearchFilter&FetchFromElasticAction.
-
-
Redis Entity Cache (
RedisEntityCacheSettings)- Object-level caching with configurable criteria and smart TTL.
-
Runtime helpers
EntityCache,ElasticIndexer,QueryCache,QueryCacheInvalidatorgive you direct programmatic access to caching and indexing behaviors.
The result is a backend that can:
-
Scale reads gracefully
-
Enforce uniqueness and constraints reliably
-
Support powerful search and list filters
-
Avoid unnecessary DB load through smart use of caching
—all while you, as the architect, remain focused on designing patterns, not infrastructure plumbing.
If you want, we can follow this with:
-
An Indexing & Caching Cookbook (pattern + code examples, e.g. “Fast autocomplete”, “Tenant-scoped dashboards”).
-
A Performance Tuning Guide for large Mindbricks projects.
Last updated Dec 29, 2025