- SOFTWARE ENGINEERING
VSCode Shortcut Wechseln in anderes File
VSCode Shortcut zum schnellen Wechseln in ein anderes File
Unintentional Cloudfront caching fooled me into thinking that a MongoDB race condition caused outdated data being displayed in my frontend.
Samuel
Software Engineer
Add the header Cache-Control: no-store
to your API responses to avoid stale data being served to clients – not all backend frameworks do it for you (e.g. Spring Boot does, Nest.js doesn't). The rest of the article explains what led me to this conclusion and how I solved it with Nest.js.
In my React frontend, I'm first sending an HTTP request to my Nest.js backend that updates a document in MongoDB, immediately followed by a second HTTP request to fetch the updated document. But it still returned the old document, as it was before the update.
Note: I know I could also make the write-request return the updated data, but in my specific case, triggering a separate read-request simplifies my frontend-setup.
I suspected that the MongoDB read operation of the second request was being run before the write operation of the previous request had even finished. I spend lots of time playing around with MongoDB read- and write-concern and read- and write-preference. To save you some time: that's not the problem here if you (like me) use an ordinary MongoDB replica set with three nodes. The default MongoDB driver settings make your write- and read operations always talk to your primary MongoDB node, therefore you can very well immediately read your own writes in a second request.
In my AWS Cloud infrastructure (defined via Terraform), Cloudfront was configured to cache responses of my API (by default for up to 5 minutes):
resource "aws_cloudfront_distribution" "cloudfront_distribution" {
# ...
default_cache_behavior {
# ...
cached_methods = ["GET"]
}
}
This had never been a problem with my Spring Boot backends, so what was my Nest.js backend doing differently? I compared responses from Spring Boot with responses from Nest.js and found that the header `Cache-Control: no-store` was missing. This header instructs Cloudfront (or any other place your response may travel through) to not cache the response. Spring Boot adds such a header by default, Nest.js doesn't. To add this header to every response in Nest.js, I'm now using a middleware:
import { Injectable, NestMiddleware } from "@nestjs/common";
import { NextFunction, Request, Response } from "express";
@Injectable()
export class PreventCachedResponsesMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
res.setHeader("Cache-Control", "no-store");
next();
}
}
Note that I'm intentionally not using a NestInterceptor
for this, because interceptors are not applied in case of e.g. a not-found error.
Now, Cloudfront doesn't cache my API responses anymore, so my frontend always displays up-to-date data instead of outdated Cloudfront cache data.
VSCode Shortcut zum schnellen Wechseln in ein anderes File
If you use Git via the terminal, here's a quick tip that might make your workflow easier.
Having a single digital place to manage my personal knowledge.
Discover the different Next.js rendering strategies—SSR, SSG, ISR, CSR, Streaming, and PPR — and how they impact performance, SEO, and business outcomes. Learn how to optimize your Next.js app for speed, scalability, and user experience with the right rendering approach.
Career
(Type)
Festanstellung, Vollzeit
(Location)
Stuttgart