How does Coda load content on its Docs? Performance

How does Coda load pages, tables and controls in its Docs and what influences performance?

I have been through all the general guidelines for optimizing performance already, so now wondering if any of this below should influence how I am (re)building my now rather big Doc.

Been through these guidelines for reference to anyone else optimizing performance

Example Doc attached below.

Setup
I have two pages:

“Databases”
This page is hidden. On this hidden page, I have 3 tables:

Table 1: People
Table 2: Company
Table 3: Orders

Table 1 and 2 are related to each other. There is no relation from Table 3 to any of the other tables.

“My view page”
Here I have a ‘Select’ control where I can select all the rows from Table 1 People.

Also, I have a view of ‘Table 1 People’. This table is filtered by the ‘Select’ control.

Questions

Assuming I just opened the Doc and I land on “My view page” as the first page, where “View of Table 1” is shown.

  1. How much of Table 1 does Coda load - only the two columns (Name and Rel_Table 2: Company) visible or also the hidden columns?
    1.1 If only the visible columns, does it in any way affect performance to have 10 hidden columns vs. 1000 hidden columns?
    1.2 Does it impact performance whether there is a lot of heavy images/files in the hidden columns?

  2. How much is loaded from Table 2: Company, given there is a relation column visible to this table?
    2.1 Does it load only the related row from Table 3?
    2.2 Does it load only the visible columns from Table 3 or also the invisible?

  3. Does Coda spend ressources to load “Table 3 Orders”? Even though it is not shown on “My view page” and it is not used as a relation column in Table 1

  4. It seems the pre-selected value in the Select Control gets loaded AFTER the table filters. Is there any way to set this up differently?
    4.1 In my example, I have the Select Control on the “My view Page” that filters “View of Table 1”. In my bigger Docs, I can see that Coda initially loads the ENTIRE table and then loads the value into the Select Control, which then filters the view. This - I assume - slows down performance of the Doc as it first needs to load e.g. 2000 rows to then filter down to 1 run afterwards when it loads the value of the Select control.
    4.2 Does it matter for performance whether the Select control is on the same page (as in my example) or e.g. on a different, hidden page?

  5. Does it impact performance whether locking is set up?


And then just to add a little twist:

Let’s say I created a new doc where I use the Sync Page function, to sync “My view Page”. Does the answers to everything above still work the same? Or does a Sync Doc e.g. load less or more tables/pages etc.?

Any input is very much appreciated!

4 Likes

Many thanks for the detailed question and example, @Maja_Overgard!

I’m the product lead supporting the performance team at Coda, so I’ll share a few overall thoughts and recommendations to keep in mind:

  • 2 key things we spend resources on from hitting “go” in your browser to when you see your doc fully loaded and interactive:
    • Downloading the data → This is all the data in your doc, which we need to download to show. The more of this you have, the longer it’ll take to see your doc.
    • Showing (rendering) the data → Turning that data like a list of names into a Table or list of projects into a Kanban board.
  • Docs are loaded in a progressive manner that optimizes for the page you’re looking at and then loads everything else in the background. While progressively loading, the doc is partially interactive. Once everything is loaded, including background content, the doc becomes fully interactive e.g., all buttons working and so on.
  • All media e.g., videos, images and so on, do not impact doc load as they’re stored outside a doc and loaded on demand.
  • Sync pages only load the source doc content when selected and don’t affect doc load. In general, you can think of their impact as similar to that of having another tab with the doc loaded — read details here.
  • You had mentioned the doc being “rather big” and are considering rebuilding. I see you have an “Orders” table in your example and one general pattern we recommend is archiving data, since I imagine this orders table will grow over time and will impact performance as it would in any other system. You can keep any aggregate values e.g., total sales or number of orders in the main doc, and move the individual orders out using things like like automations and order date for example, while still benefiting from the aggregate information — read details here.

Now on your specific questions with the high-level thoughts applied:

1 How much of Table 1 does Coda load - only the two columns (Name and Rel_Table 2: Company) visible or also the hidden columns?
1.1 If only the visible columns, does it in any way affect performance to have 10 hidden columns vs. 1000 hidden columns?
1.2 Does it impact performance whether there is a lot of heavy images/files in the hidden columns?
How much is loaded from Table 2: Company, given there is a relation column visible to this table?
2.1 Does it load only the related row from Table 3?
2.2 Does it load only the visible columns from Table 3 or also the invisible?

For Questions #1 and #2

Coda will load all the data Table 1, 2 and 3. It will do so in a progressive manner and optimize to show you content for the page you’re looking at first, and then load everything else in the background for the other pages. When it comes time to show the data, it will only spend time to show Table 1. It wont spend any time on Table 2 and 3, since those are not visible. Similarly, for hidden columns the data is there, whether or not they’re shown.

As far as all media or file attachments are concerned, these don’t impact doc load. The content is stored outside the doc and is served via a cacheable CDN, which allows images in docs to load from memory or local disk instead of loading over the web every time. This means opening/loading a doc, switching pages, opening rows, etc., should all be faster whenever images are involved.

Does Coda spend ressources to load “Table 3 Orders”? Even though it is not shown on “My view page” and it is not used as a relation column in Table 1

For Question #3

Covered in the high level thoughts, response for #1 and #2 above. Resources will be spent to download the data for Table 3 in the background and no resources spent to show the table, since the page isn’t selected.

It seems the pre-selected value in the Select Control gets loaded AFTER the table filters. Is there any way to set this up differently?
4.1 In my example, I have the Select Control on the “My view Page” that filters “View of Table 1”. In my bigger Docs, I can see that Coda initially loads the ENTIRE table and then loads the value into the Select Control, which then filters the view. This - I assume - slows down performance of the Doc as it first needs to load e.g. 2000 rows to then filter down to 1 run afterwards when it loads the value of the Select control.
4.2 Does it matter for performance whether the Select control is on the same page (as in my example) or e.g. on a different, hidden page?

For Question #4

Typically one approach we’d recommend here is what we call the inverting. Instead of a default where you show everything, then filter, you show nothing and then include things based on the filter. It’s quicker for us to render a table with no rows, and then add the specific rows that match the filter.

Moving the select control to another page won’t help as we would calculate on load. That said, changing it from personal to collaborative would help, since we’d cache the result on our servers, since the control will be in sync across all docs. The trade off is that anytime anyone changes it, it’ll affect everyone else.

The other thought, a bit more on the doc design is consider using “People” type for the “Name” column in the “People” table. To build on that, you could enable the filter bar, so you can easily select a person or use the “only show me” filters — read more here.

image.png

Does it impact performance whether locking is set up?

For Question #5

Locking should have no impact on performance. It’s helps with reducing the probability of accidental edits by anyone and for a more focused or cleaner viewing experience — more here.

Let’s say I created a new doc where I use the Sync Page function, to sync “My view Page”. Does the answers to everything above still work the same? Or does a Sync Doc e.g. load less or more tables/pages etc.?

Back to our high level thoughts of sync pages being similar to having another tab with that doc loaded, leveraging a sync page of “My View Page” in this example will load the whole source doc, so should load most of the data and then render only the pages you’ve synced in.

Happy to answer any follow on questions and feel free to read these other posts for some of the context about the details I recapped above.

9 Likes

Thanks a lot for the thorough answer! A lot of things falling into place reading your answer :clap:t2:

Four follow up and other questions under the “understand the fundamentals of Coda performance”-umbrella:

Downloading and rendering
Just to be sure, I 100% get this:

  1. In my example, I have Table 1 on my hidden page. I understand you download the entire table with all rows and all columns no matter what page I am on - correct?

  2. Let’s assume, I now have 100 views of this table on a different page. This page is hidden and never shown. This will not impact performance when I load “My View page” (or any other page than the page with the 100 views on), because Coda only renders the page I am looking at - correct?

  3. But if I open the page with the 100 views, then my Doc might be a bit slow as you now have to render 100 views - correct?

Inverting

How would you set this up in my example Doc? Assuming my Select control is still People and my Display column is text (like provided in my example; I just used “People” and “Name” as examples for something else, so it should not be a User column).

Cross Doc
All makes sense with the Sync Doc loading like “another tab”. What’s the equivalent for doing Cross Docs?

Let’s say I have a ‘Source’ Table from my ‘Source’ Doc with 3 visible columns and 2 hidden columns. Data is filtered so I have 10 visible rows and 5 hidden rows.

In my ‘Target’ Doc (where I install the Cross Doc Pack) I now display the Source Table with the 3 visible columns and no additional filters.

  1. Coda only downloads and render 10 rows - correct?
  2. Coda only downloads and render 3 columns - correct?
  3. Is the Source Doc performance impacted by the load of the table in the Target Doc?

*How does formulas/calculations impact performance?
I understand I can debug formulas/calculations to see what is running and taking up time, but would love to know the context of how these calculations impact performance:

  1. Are calculations in columns done as a part of download or rendering?

  2. How often are calculations recalculated (not date calculations, but others)?
    2.1 Let’s say in my example, I have a relation from Table 2 (Company) to Table 3 (Orders) and on Table 2, I have the column “Total price sold” where I sum the price of all orders related to this company. Are these calculations done on each load? Is the entire “Total price sold” column recalculated whenever a new row is made in the order table - or only recalculated for the row in Table 2 that this new order is related to?

  3. Formulas in buttons (under “on click”, not “visual”): do they impact download and/or rendering? Makes sense it of course impacts performance when clicking, but wondering if it also impact load time.

Looking forward to hearing your insights on these topics as well - I very much appreciate you taking the time to teach these “fundamentals”, so I (and maybe other Doc Makers out there) can learn from it!

4 Likes

You’re most welcome and many thanks for your patience — we’re happy to help and onto your 4 follow ups!

Downloading and rendering
Just to be sure, I 100% get this:

In my example, I have Table 1 on my hidden page. I understand you download the entire table with all rows and all columns no matter what page I am on - correct?

Let’s assume, I now have 100 views of this table on a different page. This page is hidden and never shown. This will not impact performance when I load “My View page” (or any other page than the page with the 100 views on), because Coda only renders the page I am looking at - correct?

There will be some impact since the doc isn’t fully interactive or ready until all data is downloaded.

That said, we do our best to first download the data for the page you’re loading so you start seeing parts of it versus others, and eventually we’ll download all data for the whole doc.

But if I open the page with the 100 views, then my Doc might be a bit slow as you now have to render 100 views - correct?

Yes, It’s more likely the page with a with 100 views might take a little longer to be fully ready versus say a page with 1 table.

That said, we have some optimizations to only render what’s on visible within the browser window. So, if it’s below the bottom of your screen we don’t need to render, since you can’t see it.

Inverting

Ayuba_Audu:Typically one approach we’d recommend here is what we call the inverting. Instead of a default where you show everything, then filter, you show nothing and then include things based on the filter. It’s quicker for us to render a table with no rows, and then add the specific rows that match the filter.

How would you set this up in my example Doc? Assuming my Select control is still People and my Display column is text (like provided in my example; I just used “People” and “Name” as examples for something else, so it should not be a User column).

You have two options here:

Simplest → You could move to a filter bar for the table and set the default values to be blank or no one — read more details here.

For example, in your current setup the “Name” column in “Table 1” and “View of Table 1” is text and you’d likely want to update to people and configure like in the screenshot below.

A bit more involvedSee the example I’ve included here of a 10K row table, which uses a similar pattern as you have with the select control. The default for all the select control is blank, which assumes we always exclude all and then you can include items based on what’s selected after loading.

Cross Doc
All makes sense with the Sync Doc loading like “another tab”. What’s the equivalent for doing Cross Docs?

Let’s say I have a ‘Source’ Table from my ‘Source’ Doc with 3 visible columns and 2 hidden columns. Data is filtered so I have 10 visible rows and 5 hidden rows.

In my ‘Target’ Doc (where I install the Cross Doc Pack) I now display the Source Table with the 3 visible columns and no additional filters.

Coda only downloads and render 10 rows - correct?

Coda only downloads and render 3 columns - correct?

Is the Source Doc performance impacted by the load of the table in the Target Doc?

For #1 and #2 — yes you’re correct. Cross-doc will only send over the visible data i.e., visible columns and rows not filtered out with collaborative filter — more details here.

The source doc performance isn’t really impacted by the target doc syncing in rows via Cross-doc.

*How does formulas/calculations impact performance?
I understand I can debug formulas/calculations to see what is running and taking up time, but would love to know the context of how these calculations impact performance:

Are calculations in columns done as a part of download or rendering?

Downloading and rendering aren’t truly sequential i.e., we’re typically doing some portion of both at the same time, else you’d be looking at a loading spinner for a while especially on large docs. This means some calculations will start running before the data download is complete, and the results will be incomplete until all data is finished downloading.

How often are calculations recalculated (not date calculations, but others)?
2.1 Let’s say in my example, I have a relation from Table 2 (Company) to Table 3 (Orders) and on Table 2, I have the column “Total price sold” where I sum the price of all orders related to this company. Are these calculations done on each load? Is the entire “Total price sold” column recalculated whenever a new row is made in the order table - or only recalculated for the row in Table 2 that this new order is related to?

The short version is we run calculations when we detect something has changed and a calculation has dependencies on that change. This means calculations run as often as needed to ensure you’re always looking at the latest information.

This means for the example you had:

  • Are these calculations done on each load? → Yes.
  • Is the entire “Total price sold” column recalculated whenever a new row is made in the order table - or only recalculated for the row in Table 2 that this new order is related to? → The latter i.e., only the row in Table 2 that has dependencies on orders.

We do have optimizations in place that can help speed up a bunch of known scenarios and sometimes calculations can get backed up in really busy docs or expensive calculations.

Formulas in buttons (under “on click”, not “visual”): do they impact download and/or rendering? Makes sense it of course impacts performance when clicking, but wondering if it also impact load time.

Generally speaking they shouldn’t have any impact until you interact with them or you have a large amount of buttons — this is less about the formulas and more loading all the buttons.

That said, you could have something that triggers them and has impact e.g., a time based automation that pushes buttons and has a expensive formula which runs right about when you’re opening and loading the doc.

Tesco has a motto that every little helps and so every tweak or careful consideration can add up.

6 Likes

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.