Should you always optimize your Microsoft Graph queries?


Sometimes, you can improve your app’s performance by not optimizing your Microsoft Graph queries. Here is why.

Only the best user experience

When building apps, we always look for ways to improve the experience for our users. We want our apps to be blazing-fast. And so we optimize our assets, deploy them on CDNs, remove unnecessary metadata and only load the data that we need. Makes sense, doesn’t it? The less data we request, the faster we can get it and the faster we can show it our app, right? Well, yes and no.

Looking just at the requests, it makes sense to just download the data that you need, when you need it. After all, a request for a smaller set of data will be faster. But what if you look at the app as a whole?

Consider the big picture when optimizing requests

Say, you’re building an app that shows some information about the current user. In one place of the app, you show their display name and job title. In another place, you show their colleagues.

To get the information about the current user, you call the Microsoft Graph /me endpoint. Following the idea of optimizing performance by just retrieving the data you need, you request just the properties you need: /me?$select=displayName,jobTitle.

Next, to retrieve the list of colleagues, you call Microsoft Graph to retrieve the manager of the current user, their reports, and also the ID of the current user to exclude them from the list of manager’s reports and show a list of colleagues. Because originally you retrieved only the displayName and jobTitle of the current user, you need to call the /me endpoint again to retrieve the user’s ID. And that’s exactly the problem: because you optimized the original request, now you need to execute two requests instead of one. Two requests to Microsoft Graph will rarely if ever, be faster than one. So much for better performance.

Optimizing apps for performance is an art and to do it right you need to look at your app from multiple angles, taking many variables into account. You also need to look at your app as a whole. Sometimes, retrieving more information than you need, might be faster than just retrieving what you need when you need it in multiple requests. Depending on how you build your app, by expanding your requests, you might improve your app’s performance!

What if you’re using Microsoft Graph Toolkit

Using Microsoft Graph Toolkit is the easiest way to connect your app to Microsoft 365. Next to authentication providers and components, which help you connect your app to Microsoft 365 and show data from Microsoft 365, the toolkit implements caching that helps you improve the performance of your app.

Consider the scenario I mentioned earlier when working with Microsoft Graph Toolkit. When you use the Get component with caching enabled, the toolkit caches the retrieved data using the request URL as the cache key. By using two different - optimized URLs, the toolkit would issue two requests and cache data under two separate keys:

<!-- request #1 -->
<mgt-get resource="/me?$select=displayName,jobTitle" cache-enabled="true">
<template>
    {{this.displayName}} ({{this.jobTitle}})
</template>
</mgt-get>
...
<!-- request #2 -->
<mgt-get resource="/me?$select=id" cache-enabled="true">
<template>
    {{this.id}}
</template>
</mgt-get>

If you expanded the request to retrieve more data than it needs, the toolkit would need only one request to Microsoft Graph. The second Get component would get the data from cache, because it has the same URL:

<!-- request #1 -->
<mgt-get resource="/me?$select=displayName,jobTitle,id" cache-enabled="true">
<template>
    {{this.displayName}} ({{this.jobTitle}})
</template>
</mgt-get>
...
<!-- request #1 (from cache) -->
<mgt-get resource="/me?$select=displayName,jobTitle,id" cache-enabled="true">
<template>
    {{this.id}}
</template>
</mgt-get>

There is just one thing. Depending on how your app is built though, despite using the same URL you might see your app issue two exact Graph requests. Why? Haven’t we just concluded that by using the same URLs we should get the data from the cache for subsequent requests?

It all has to do with timing. Microsoft Graph Toolkit doesn’t manage its requests centrally. Each component issues its requests. If the data that it needs isn’t available in the cache, it will call Microsoft Graph. If the two Get components are next to each other, and the second component loads before the first’s request has been resolved and processed, it will call Graph instead of waiting for the response from the other Get component. The same applies to any other toolkit component. If the data has been previously retrieved and cached, it will be loaded from the cache without calling Graph but one component will not wait for another.

Summary

Optimizing your app’s performance isn’t binary. Sometimes, what seems counterintuitive at first, can give you better results. If you want to offer your users the best experience, look at your app as a whole. Think about how the app will be used and what data it will need at any point. And only then start thinking about optimizations and caching. This is how you’ll get the best results.

Photo by Marc-Olivier Jodoin on Unsplash

Others found also helpful: