Multiple contract keys on a template

I have 2 different APIs that need to be able to retrieve a particular contract based on 2 different criteria (contract keys):

template X
    with 
        a: Text
        b: Text
        p: Party
    where
        signatory p
  • API1 should be able to fetchByKey/lookupByKey on contracts of template X using key (a,p).
  • API2 should be able to fetchByKey/lookupByKey on contracts of template X using key (b,p).

Per my understanding, there is no way to define multiple contract keys on a template. If this is correct, how can I achieve the above?
Please note, I can only use the gRPC API for this so I cannot do field-level queries, nor do I have the option of using an application layer database / custom query store.

Even though access by key is optimized, keys themselves are not really meant to be a way to query a contract, but rather to define an identity that can outlive the contract ID and tie together states represented by multiple “incarnations” of an immutable contract. As such, you cannot assign two keys to the same contract.

I would like to understand why you’re bound to the Ledger API and cannot have a component that takes care of producing a view for your application.

Reason the client doesn’t want to use a view is because this querying is part of a critical path operation and the client doesn’t want to use external storage on the critical path due to potential synchronisation delays between the ledger and the external storage. The client writes data to the ledger, can do an immediate query and write the next piece of throughput-critical data based on the result of the query.
There is also a concern from the client on introducing external (non-ledger) system dependencies for critical path operations, increasing the error/operational surface area.

As such, the client is already using external storage for historical/auditing purposes.