I'm one of the engineers that worked on this - would love to hear any thoughts or feedback anyone has! How does your team deploy your Next.js frontend?
I'm curious where the majority of the win came from? Do you have a before & after trace handy to compare what changed?
Looks like you opted not to use SSR, which I think is a good choice for smaller teams. CSS changes are unlikely to account for a large performance win. Did you use a CDN before? Perhaps the biggest win was moving to a better CDN + built-in preloading/prefetching provided by NextJS?
I'm curious where the majority of the win came from?
Great question! The boost can be explained by JS vs. raw HTML+CSS performance.
In the past, we sent a dummy loading screen but we then had to download tons of JS + run that to even show a "real" loading screen (i.e. page-specific loading screen).
Now, the HTML response (which you can inspect yourself, `curl https://my.causal.app`) already has a skeleton of the page, which doesn't need any JS to download and run before showing the "real" loading screen.
The UX is better because users spend noticeably less time staring at a blank screen and there's much less layout shift too!
Which metric improved by 70%? Time to show the skeleton? I agree the skeleton is quite good. I see it takes about 350ms to show the skeleton and about 1s to show my content.
backend API calls will be very fast because of colocation on GCP
Any chance you guys measured this speed difference? Was there a path considered to locally cache api responses on the vercel server or in middleware somewhere?
Trying to reason about a similar decision right now. There's probably a simple way to cache hot backend request/responses to get static-like speeds?
Any chance you guys measured this speed difference?
No, but we actually can get some comparison, since as I mentioned we host preview apps on Vercel! I did some quick tests right now, and it looks like based on logs, the API request to our Node backend takes:
- From Vercel: ~300ms worst case, ~40ms best case
- From within GCP: ~120ms worst case, ~20ms best case
These numbers are very approximate, but hopefully still insightful! And I'm not sure about the cause of the variance, there are quite a few links in the chain that could be at fault.
Was there a path considered to locally cache api responses on the vercel server or in middleware somewhere?
We do cache the responses using a CDN; adding another layer of caching beyond this wouldn't help much since at that point we need to fetch fresh results anyway.
There's probably a simple way to cache hot backend request/responses to get static-like speeds?
Yes, the CDN cache I mentioned is almost instant in good conditions (~2ms on my internet connection) - the problem is sometimes you do actually need updated data, and having huge variance between the cached response speed and the uncached response speed could be undesirable for users.
Comments
I'm one of the engineers that worked on this - would love to hear any thoughts or feedback anyone has! How does your team deploy your Next.js frontend?
I'm curious where the majority of the win came from? Do you have a before & after trace handy to compare what changed?
Looks like you opted not to use SSR, which I think is a good choice for smaller teams. CSS changes are unlikely to account for a large performance win. Did you use a CDN before? Perhaps the biggest win was moving to a better CDN + built-in preloading/prefetching provided by NextJS?
Great question! The boost can be explained by JS vs. raw HTML+CSS performance.
In the past, we sent a dummy loading screen but we then had to download tons of JS + run that to even show a "real" loading screen (i.e. page-specific loading screen).
Now, the HTML response (which you can inspect yourself, `curl https://my.causal.app`) already has a skeleton of the page, which doesn't need any JS to download and run before showing the "real" loading screen.
The UX is better because users spend noticeably less time staring at a blank screen and there's much less layout shift too!
Which metric improved by 70%? Time to show the skeleton? I agree the skeleton is quite good. I see it takes about 350ms to show the skeleton and about 1s to show my content.
Yep - the metric was First Contentful Paint, which is basically the time-to-skeleton in our case :)
Any chance you guys measured this speed difference? Was there a path considered to locally cache api responses on the vercel server or in middleware somewhere?
Trying to reason about a similar decision right now. There's probably a simple way to cache hot backend request/responses to get static-like speeds?
No, but we actually can get some comparison, since as I mentioned we host preview apps on Vercel! I did some quick tests right now, and it looks like based on logs, the API request to our Node backend takes:
- From Vercel: ~300ms worst case, ~40ms best case
- From within GCP: ~120ms worst case, ~20ms best case
These numbers are very approximate, but hopefully still insightful! And I'm not sure about the cause of the variance, there are quite a few links in the chain that could be at fault.
We do cache the responses using a CDN; adding another layer of caching beyond this wouldn't help much since at that point we need to fetch fresh results anyway.
Yes, the CDN cache I mentioned is almost instant in good conditions (~2ms on my internet connection) - the problem is sometimes you do actually need updated data, and having huge variance between the cached response speed and the uncached response speed could be undesirable for users.
thanks for those figures! It makes sense on the cache invalidation given the type of content Casual is serving.
It will be interesting once Vercel offers colo'd data sources and more with their edge rendering, which they just announced: https://vercel.com/blog/regional-execution-for-ultra-low-lat...
ISR will give you static-like speeds
https://vercel.com/docs/concepts/incremental-static-regenera...