Unlock seamless workflows and faster delivery with our latest releases - Join the deep dive

Maximum attribute limits and nesting depth in Sanity.io

27 replies
Last updated: Jul 14, 2020
Hey! Is there a maximum amount of types you can specify in the
of
attribute of a field with
type: array
? Thanks!
Jul 8, 2020, 7:23 PM
Hi User! I don’t think there’s an actual limit but things might get a bit cumbersome or slow at some point. However, there is an overall attribute limit of 2000 so adding tons of unique paths (each type will add to this) might bring you closer to that one. More info on limits in general: https://www.sanity.io/docs/technical-limits
You’ll probably be alright though - what’s the use case?
🙂
Jul 8, 2020, 10:07 PM
It’s a field that allows a list of different building blocks inside. It’s a good point what you’ve raised, as we intended to make the structure some-what recursive with restrictions
Jul 9, 2020, 12:30 PM
Definitely we’ll see about these 2.
Maximum number of unique attributes across all documents: 2000 attributes
Maximum attribute nesting depth: 20 levels 

Jul 9, 2020, 12:31 PM
Is there a way to check via CLI or Studio what is the current value of those? To see if that’s a problem before we pivot to a different content model. Does something appear on the Studio as you go over the limits, or does it only happen when importing faulty datasets? If someone is hovering over those values does Sanity contact them or what’s the way to know?
Jul 9, 2020, 12:39 PM
Thanks!
Jul 9, 2020, 12:45 PM
Regarding attribute nesting, not sure if we have any endpoint with stats on that so it’s probably good to keep an eye out for this yourself, particularly when using nested block content structures for example.
You can monitor your attribute stats via
<projectId>.<http://api.sanity.io/v1/data/stats/|api.sanity.io/v1/data/stats/><datasetName>
- check
fields.count.value
(the one right next to
limit: 2000
). You will start seeing errors if you exceed this limit but no warnings when you’re close to it. That’s something we would still like to improve since it’s helpful to get a timely warning, particularly as it relates to content modelling and it can be tricky to change everything after the fact.
Jul 9, 2020, 12:58 PM
Thanks!
Jul 9, 2020, 1:09 PM
One last thing, for attribute nesting, is there an easy way to check?Document of type… “Section”, has a field content.

section.content.alpha.bravo.charlie.delta.echo.foxtrot.golf.hotel….
Jul 9, 2020, 1:33 PM
that’ll be disabled to edit in Studio and/or break an import as those keys become +20?
Jul 9, 2020, 1:34 PM
or is there a different calculation here
Jul 9, 2020, 1:34 PM
I’d have to check with the team to see how the limit is enforced in this case - do you already have a path with +20 nested keys?
Jul 9, 2020, 1:43 PM
One of my colleagues does haha now it makes all sense. As it stopped him from importing a dataset with a JSON that ended up having…
content.0.bars.0.contentBlock.content.list.0.columns.2.contentBlock.content.list.4.columns.2.contentBlock.content.list.0.style.designTokenTypography
Jul 9, 2020, 1:49 PM
A bit of an edge case, and we can certainly remove a few to go back to minus 20, but certainly a flag to see if we can save some keys to avoid generating structures that are simple but still nested
Jul 9, 2020, 1:50 PM
Indeed, it’s probably a good opportunity to review the content model, as usually getting to the nested keys limit means you’re at risk of approaching the attribute limit as well. Sorry you’re running into this one though.
Jul 9, 2020, 1:54 PM
No worries! We love working with Sanity 🙌 . My final question would be… if this content structure is on a documentType1, and on a documentType 2
Jul 9, 2020, 2:04 PM
does it generate N attributes or does it count like the same towards the 2000 limit
Jul 9, 2020, 2:04 PM
assuming the final key ends up being
contentBlock.content.list.0.columns.2.contentBlock.content.list.4.columns.0.title....
, does it count as 1 attribute for
documentType1
and 1 more attribute for
documentType2
? or is the “top level document type” not part of the unique path used to calculate unique attributes
Jul 9, 2020, 2:05 PM
That’s a great question and one I’m not sure about. As far as I know, it looks for similar paths regardless of the enclosing document name but it would be good to put that to the test.
However, the example you give would be more than a single path even if it doesn’t differentiate between the document types. As an example:

{
  "foo": [
    {
      "bar":…,
      "baz":…
    },
    {
      "bar":…,
      "baz":…
    },
    {
      "bat": {
        "bar":…
      }
    }
  ]
}

This leads to the following six paths (attributes):

- foo -> an array
- foo[] -> an object
- foo[].bar -> a string
- foo[].baz -> a string
- foo[].bat -> an object
- foo[].bat.bar -> a string
Jul 9, 2020, 2:44 PM
Oh totally, that’s expected. My only concern is whether I can put
foo
fields on different documents (As a field of the top level) and still only end up with N paths…

- foo -> an array
- foo[] -> an object
- foo[].bar -> a string
- foo[].baz -> a string
- foo[].bat -> an object
- foo[].bat.bar -> a string
instead of N*M (where M is the amount of documents using it) paths

- documentType1.foo -> an array
- documentType1.foo[] -> an object
- documentType1.foo[].bar -> a string
- documentType1.foo[].baz -> a string
- documentType1.foo[].bat -> an object
- documentType1.foo[].bat.bar -> a string

- documentType2.foo -> an array
- documentType2.foo[] -> an object
- documentType2.foo[].bar -> a string
- documentType2.foo[].baz -> a string
- documentType2.foo[].bat -> an object
- documentType2.foo[].bat.bar -> a string

Jul 9, 2020, 3:25 PM
Fair concern! I’ll check this for you because I’m not actually sure 🙂 Will post back here tomorrow hopefully.
Jul 9, 2020, 3:26 PM
Thank you so much!
Jul 9, 2020, 3:29 PM
Hi again User, I can confirm you would end up with N*M paths in the above case, so the document types are indeed a multiplier for the number of paths I’m afraid.
Jul 10, 2020, 8:35 AM
Hi User, thanks for the answer.
And if
documentType2.foo[].bat
there are actually 2 different objects that could use the name
bat
(let’s imagine that internal object could have different _type, and has different fields inside), would
documentType2.foo[].bat
always count as 1 path? Obviously nested paths would vary.
Jul 10, 2020, 10:26 AM
Hi User, thanks so much for all the help! This is being super helpful for us.

Alternatively I’m guessing we could just create the recursion using references to a document (instead of nesting objects directly) which would certainly bring down the total possible paths (exponentially!), but will make reading this considerably harder. Although I think
_raw
fields with
resolveReferences: { maxDepth: N }
should sort it on Gatsby GraphQL and some pretty cool GROQ queries would also work alternatively.
Let’s go with a basic example:
document 0

_type: contentBlock
id: 0
content.list.0 // {} object of _type here is one of the many options available, in this case contentItemColumns
content.list.0.columns  // [] array of refs to type: contentBlock
content.list.0.columns.0._ref = 1
content.list.0.columns.1._ref = 2
document 1

_type: contentBlock
id: 1
content.list.0 // {} object of another _type here, contentItemHeading
document 2

_type: contentBlock
id: 2
content.list.0  // {} object of another _type here, contentItemImage
1.
Would you recommend a strategy like this instead of actually nesting the objects?2.
content.list.0
being a typeof (in JS)
object
, despite that on document 0 it is of Sanity
_type contentItemColumns
, on document 1 of
_type contentItemHeading
, and on document 2
_type contentItemImage
does it count as one unique attribute or does it count as 3 different? Of course that the internal fields of those 3 types would generate unique paths (for example as contentItemColumns has field
columns
and the others don’t), but there’s also an opportunity here if they all have a field called
foo
of type
string
and it counts as just 1 unique attribute instead of 3.Thanks for the patience and the great support, I think this is the last bit of information needed for us to take a second step at this and improve our modelling without ever hitting the technical limits!
Jul 10, 2020, 10:27 AM
Leaving an update here case in it helps anyone!
I was able to confirm array with multiple types inside (as
of
) should count as just one unique path as the path Sanity counts is…
content.list - array
content.list[] - object (it doesn't matter if N different types can be this object)
content.list[].eachField (here's where having lots of different types would start increasing the possible paths)
Jul 14, 2020, 2:17 PM
If you need help reviewing what paths your project is generating…
1. Install
https://www.sanity.io/docs/the-vision-plugin 2. Use the query
*
to fetch the entire dataset.3. Copy and save the entire JSON onto your disk
4. Use this package
https://www.npmjs.com/package/json-list-paths to do
jlp(yourJSON).list()
It’s a bit off (+-10-20 paths) but it gives you a pretty good understanding!
Jul 14, 2020, 2:19 PM
const jlp = require('json-list-paths');
const json = require('./dataset.json');
const result = jlp(json).list();
console.log(result);
console.log(`-> There were a total of ${result.length} paths in the JSON.`)

Jul 14, 2020, 2:22 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?