Skip to main content


To make efficient lookups, Pathom uses a series of indexes generated from the user resolvers.


This is the most important index to understand how Pathom processes the data.

oir stands for outputinputresolver.

In other words, this is the index that tells Pathom which are the paths available to reach a given attribute in the system.

Let's look at an example and talk over it:

; for this resolver
(pco/defresolver product-by-id [{:keys [acme.product/id]}]
{::pco/input [:acme.product/id]
::pco/output [:acme.product/name
(fetch-product id))

; we get this index-oir
{:acme.product/name {{:acme.product/id {}} #{product-by-id}}
:acme.product/price {{:acme.product/id {}} #{product-by-id}}
:acme.product/in-stock? {{:acme.product/id {}} #{product-by-id}}}}

With this index, Pathom can ask: How can I fetch :acme.product/price in the system? For which the answer is:

{{:acme.product/id {}} #{product-by-id}}

Or in plain english: The index says you can fetch the product price, given you provide some product id, using the edge product-by-id.

The input in this index uses the shape descriptor format.

This is an overview of this index, for more details on how the planner uses it, check the planner page.


This index tells, for given attribute set (with empty, one or more items), which attributes are directly reachable (one resolver distance) from that set.

io stands for inputoutput.

Here is what index-io looks like, using the same resolver from our previous example:

{:acme.product/name {}
:acme.product/price {}
:acme.product/in-stock? {}}}}

The output part uses the shape descriptor format.

Smart maps use this index to figure reachable attributes when used in "reachable mode".

This is a good index to create auto-complete features in editors for Pathom integration.


This index contains accumulated information about how a specific attribute relates to other attributes and resolvers.

Let's use the full-name resolver example to demonstrate the index-attributes at play:

(pco/defresolver full-name [{::keys [first-name last-name]}]
{::full-name (str first-name " " last-name)})

{#{::first-name ::last-name} {:com.wsscode.pathom3.connect.indexes/attr-id #{::first-name ::last-name}
:com.wsscode.pathom3.connect.indexes/attr-provides {::full-name #{:full-name}}
:com.wsscode.pathom3.connect.indexes/attr-input-in #{full-name}}
::first-name {:com.wsscode.pathom3.connect.indexes/attr-id ::first-name
:com.wsscode.pathom3.connect.indexes/attr-combinations #{#{::first-name ::last-name}}
:com.wsscode.pathom3.connect.indexes/attr-input-in #{full-name}}
::last-name {:com.wsscode.pathom3.connect.indexes/attr-id ::last-name
:com.wsscode.pathom3.connect.indexes/attr-combinations #{#{::first-name ::last-name}}
:com.wsscode.pathom3.connect.indexes/attr-input-in #{full-name}}
::full-name {:com.wsscode.pathom3.connect.indexes/attr-id ::full-name
:com.wsscode.pathom3.connect.indexes/attr-reach-via {#{::first-name ::last-name} #{full-name}}
:com.wsscode.pathom3.connect.indexes/attr-output-in #{full-name}}}}

The first level of the index is the attribute itself, the details we can explain key by key:


Contains the ID of the attribute, it may be a keyword (as seen in the example) or also a set in cases of attribute combinations.


A set containing a list of all resolvers in which this attribute appears as an input.


A set containing a list of all resolvers in which this attribute appears as an output.


This is a sub-index, telling what other attributes are reachable from this attribute, by which resolver.


This is a sub-index, telling what other attributes you can use to reach the current, by which resolver.


A set with all the input combinations that this attribute appears in.


In this index, you can look up resolvers by their name. Using both product-by-id and full-name resolvers, this is what the index-resolvers looks like:

{:config {:com.wsscode.pathom3.connect.operation/input [:acme.product/id]
:com.wsscode.pathom3.connect.operation/requires {:acme.product/id {}}
:com.wsscode.pathom3.connect.operation/output [:acme.product/name :acme.product/price :acme.product/in-stock?]
:com.wsscode.pathom3.connect.operation/provides {:acme.product/name {}
:acme.product/price {}
:acme.product/in-stock? {}}
:com.wsscode.pathom3.connect.operation/op-name product-by-id}
:resolve product-by-id--23075}

{:config {:com.wsscode.pathom3.connect.operation/input [::first-name ::last-name]
:com.wsscode.pathom3.connect.operation/requires {::first-name {} ::last-name {}}
:com.wsscode.pathom3.connect.operation/output [::full-name]
:com.wsscode.pathom3.connect.operation/provides {::full-name {}}
:com.wsscode.pathom3.connect.operation/op-name full-name}
:resolve full-name--23079}}}


In this index, you can look up mutations by their name. Here is an example of what it looks like:

;; the mutations

(pco/defmutation create-product [{:keys [acme.product/name acme.product/price acme.product/in-stock?]}]
{::pco/output [:acme.product/id]}
(create-product name price in-stock?))

{:acme.product/id {}},
[:acme.product/name :acme.product/price :acme.product/in-stock?],
:com.wsscode.pathom3.connect.operation/output [:acme.product/id],
#object[demos.async_mutations$create_product__19314 0x2e4c1d84 "demos.async_mutations$create_product__19314@2e4c1d84"]}},}