Stores and Store Routes
Stores and store routes control where Mach5 writes index data.
What is a store?
A store is the object storage location where Mach5 persists index data.
Examples:
s3://example-bucket/primary-index-datas3://example-bucket/secondary-index-data
The store configuration defines the bucket and optional prefix. It does not decide which index goes there.
What is a store route?
A store route decides which store a newly created index should use.
Each store route has:
- a target
store_id - an index name regex in
pattern - a numeric
priority - an optional namespace regex in
namespace_pattern
At index creation time, Mach5 evaluates the configured store routes, picks the first matching route, and records the chosen store on the index.
After that, the index keeps using that store. Changing store routes later does not move existing indexes.
The examples below use the StoreRouteConfig payload shape:
{
"store_id": "<store-id>",
"priority": 10,
"pattern": ".*",
"namespace_pattern": null
}
How matching works
Store route matching is based on the index name, not on:
- the store bucket
- the store prefix
- the warehouse name
- the
/warehouse/...URL
pattern is a regular expression matched against the index name.
Examples:
.*matches every index name^logs-.*matches index names that start withlogs-^metrics-.*matches index names that start withmetrics-
Regular expressions are not implicitly anchored. If you want to match the beginning of the index name, use ^.
How priority works
Higher numeric priority wins over lower numeric priority.
For example, if two generic routes both match an index:
{"pattern": ".*", "priority": 0}{"pattern": ".*", "priority": 10}
the route with priority 10 is selected.
One important exception applies:
- Mach5 evaluates routes with a
namespace_patternfirst - Mach5 only evaluates routes without a
namespace_patternif no namespace-specific route matches
So a matching namespace-specific route can win over a generic route even if the generic route has a higher numeric priority.
Common examples
Single-store deployment
If you only have one store, use one simple catch-all route:
{
"store_id": "<primary-store-id>",
"priority": 10,
"pattern": ".*",
"namespace_pattern": null
}
This routes all newly created indexes to the same store.
Two stores with disjoint index prefixes
Use anchored regexes when the index name itself tells you which store to use:
[
{
"store_id": "<logs-store-id>",
"priority": 10,
"pattern": "^logs-.*",
"namespace_pattern": null
},
{
"store_id": "<metrics-store-id>",
"priority": 10,
"pattern": "^metrics-.*",
"namespace_pattern": null
}
]
Because these rules are intended to match different index names, priority should not matter in normal use.
Override all new indexes to a new store
If both routes match every index, priority decides which store new indexes use:
[
{
"store_id": "<existing-store-id>",
"priority": 0,
"pattern": ".*",
"namespace_pattern": null
},
{
"store_id": "<new-store-id>",
"priority": 10,
"pattern": ".*",
"namespace_pattern": null
}
]
In this case, new indexes are routed to <new-store-id>.
Existing indexes that were already created in <existing-store-id> stay there.
Namespace-specific routing
You can also route by namespace:
[
{
"store_id": "<prod-store-id>",
"priority": 5,
"pattern": ".*",
"namespace_pattern": "^prod$"
},
{
"store_id": "<default-store-id>",
"priority": 100,
"pattern": ".*",
"namespace_pattern": null
}
]
An index created in namespace prod uses <prod-store-id>, even though the generic route has a higher priority.
When do you need multiple stores?
Most deployments only need one store and one route with pattern: .*.
Multiple stores are mainly useful when you intentionally want different sets of indexes to live in different object storage locations, for example:
- gradual cutover from one storage prefix to another
- keeping different index families in different prefixes or buckets
- environment-specific or namespace-specific routing