User Guide
Everything you need to install, configure, and build with Montycat — from getting started to governance, advanced operations, and security.
Retrieval
Single record retrieval
You can retrieve a single record by it's key (id).
A key can be regular ordered key or custom key.
You can embed a key in that case you will receive a __key__ and __value__ fields in response.
from keyspaces import Employees
res1 = await Employees.get_value(key = "128222336824100726154851618391811195396")
res2 = await Employees.get_value(custom_key = "myCustomKey")
# {"status": True, "payload": {"username": "Name", "location": "Location", "age": 21}, "error": None}
res3 = await Employees.get_value(key = "128222336824100726154851618391811195396", key_included = True)
# {
# "status": True,
# "payload": {
# "__key__": "128222336824100726154851618391811195396",
# "__value__": {"username": "Name", "location": "Location", "age": 21}
# },
# "error": None
# }Retrieve with pointers
If you define pointers (references to another record in a different keyspace) in a schema, you can resolve them when querying by setting a special flag.
When the flag is enabled:
- The pointer values will be automatically fetched and integrated into the original record's body.
- This allows you to work with a fully hydrated object instead of manually resolving references across keyspaces.
Pointers enable Montycat to act like a data mesh join mechanism, keeping data physically distributed but logically unified.
When the flag is disabled you will only see the only original record.
This avoids additional fetch overhead and is useful for lightweight or high-performance reads.
from keyspaces import Employees
res1 = await Employees.get_value(key = "128222336824100726154851618391811195396", with_pointers = True)
res2 = await Employees.get_value(custom_key = "myCustomKey", with_pointers = True)
# {
# "status": True,
# "payload": {
# "username": "Name",
# "location": "Location",
# "age": 21,
# "department": {
# "name": "IT",
# "employees": 20
# }
# },
# "error": None
# }Multiple records retrieval
Montycat allows you to retrieve multiple values in a single request.
This improves efficiency and reduces network overhead compared to fetching keys individually.
When retrieving multiple values you can:
- Provide a list of regular keys (system-generated IDs).
- Provide a list of custom keys (user-defined identifiers).
Optionally enable pointer resolution so that referenced records from other keyspaces are automatically integrated into the result.
The response will always include:
- status → Whether the bulk operation succeeded.
- payload → Contains succeded (records successfully retrieved) and failed (keys that could not be found or resolved).
- error → Error message if the whole operation failed.
from keyspaces import Employees
keys_to_get = [
'128222336824100726154851618391811195396',
'254672336824100726154851618391811195333',
]
custom_keys_to_get = ['myCustomKey1', 'myCustomKey2']
res1 = await Employees.get_bulk(keys=keys_to_get)
res2 = await Employees.get_bulk(keys=keys_to_get, custom_keys=custom_keys_to_get, with_pointers=True)
# {
# "status": True,
# "payload": {
# "succeded": [
# {"username": "Name1", "location": "Location1", "age": 21},
# {"username": "Name1", "location": "Location1", "age": 22},
# ],
# "failed": []
# },
# "error": None
# }
# or if all failed: {"status": False, "payload": None, "error": "Error Text"}
# or if some of retrievals failed:
# {
# "status": True,
# "payload": {
# "succeded": [
# {"username": "Name1", "location": "Location1", "age": 21},
# ],
# "failed": [
# "254672336824100726154851618391811195396"
# ]
# },
# "error": None
# }Limit output
When working with large sets of keys, you may not want to fetch everything at once.
Montycat provides an option that lets you control the range of records returned in a single call.
This is especially useful for:
- Pagination → Fetching results in manageable chunks (e.g., page 1 = first 50, page 2 = next 50).
- Batch processing → Processing subsets of a large dataset iteratively.
- Performance optimization → Preventing memory overload when working with very large key lists.
Range and bulk reads also accept an order option. Use ascending to scan from oldest to newest or descending to scan from newest to oldest. Limits use a half-open [start, stop) range and are applied in the chosen direction, which makes forward and reverse pagination deterministic.
Note: The limit option is only available for persistent keyspaces. In-memory keyspaces always return all keys.
from keyspaces import Employees
from montycat import ResultOrder
res1 = await Employees.get_bulk(
limit=[2, 4],
order=ResultOrder.DESCENDING,
) # returns positions [2, 4) while scanning newest to oldestGet keys only
Montycat also allows you to fetch keys without values.
This is useful for metadata operations, prefetching, or scanning datasets before performing full retrievals.
Behavior
- In-memory keyspaces → return all existing keys without a configurable order.
The limit option is not available. - Persistent keyspaces → support the limit and order parameters.
Keys are returned in deterministic order by their internal insertion timestamp; choose ascending or descending explicitly.
This allows you to paginate over stored data efficiently.
from keyspaces import Employees, EmployeesInMem
from montycat import ResultOrder
res1 = await EmployeesInMem.get_keys() # In-memory keyspaces return all keys
res2 = await Employees.get_keys(limit=[20, 40], order=ResultOrder.ASCENDING)
# {
# "status": True,
# "payload": ["128222336824100726154851618391811195396", "254672336824100726154851618391811195396"],
# "error": None
# }Get keys by Volume
Montycat supports retrieving keys based on their associated volume.
This is particularly useful for persistent keyspaces where data is sharded across multiple volumes for scalability and performance.
- You can specify a particular volume number to fetch keys stored within that volume.
- This allows targeted retrieval of keys from specific data shards, which can be useful for maintenance, analysis, or debugging.
Note: If you want to retrieve all custom keys you have to specify volume as 0.
from keyspaces import Employees
from connection import connection #connection.py
res1 = await connection.get_structure_available()
# {"status": True, "payload": <JSON tree of all available structures>, "error": None}
# list of volumes will be included in response
res2 = await Employees.get_keys(volumes=['32009234234234234'])
res3 = await Employees.get_keys(latest_volume=True)
# {
# "status": True,
# "payload": ["128222336824100726154851618391811195396", "254672336824100726154851618391811195396"],
# "error": None
# }