A Redis cache for Google Maps API calls stores route and place results for a fixed time so a repeated origin and destination never hits Google twice. In a Node.js API built with Fastify, Clean Architecture and MongoDB, that means one middleware, a cache key, and a TTL passed as a parameter instead of hard-coded.
Redis cache for Google Maps API calls in a Node.js API
A Redis cache for Google Maps API calls keeps each place or route response for a set time so repeated lookups never reach Google twice. In the Node.js tracking API from Dev Doido's CrazyStack TypeScript course, the cache sits in front of two Fastify endpoints and one map adapter.
The setup exposes two routes. findPlaces returns candidate street addresses from a text query, and getDirections returns a route preview between two place IDs. Both call an adapter that wraps Google Maps, and both sit behind a cache middleware built on Redis through the Node client.
The reason to cache is cost and latency. A driver app redraws the same preview route many times while a user scrolls the map. Google bills per request, so serving the second and third lookups from Redis removes spend that produces no new information for the user.
Why the API needs findPlace and getDirections as separate endpoints
The API needs findPlace and getDirections as separate endpoints because users know street names, not Google place IDs. The front end offers an autocomplete field, sends the typed text to findPlace, and receives a candidate list with place IDs that the directions call can then consume.
The previous lesson's use case already called getDirections, but only to persist a generated route. A user who wants to preview that route before starting a trip has no such record. The new endpoint supplies the preview; the stored route still comes from the use case that writes to the rides repository.
Calling the adapter directly from the controller would bypass the existing structure. The project routes requests through an adapter class that takes a controller, so each endpoint got its own load controller plus a factory, slotting the maps adapter into the existing Clean Architecture vertical slice.
How to wire the Redis cache middleware into Fastify
The Redis cache middleware is attached to the Fastify route, and it stores the response for a time-to-live passed in from the route instead of a hard-coded value. The earlier lesson had fixed 120 seconds inside the function, which works for one route and stops working as soon as routes need different lifetimes.
The change is small. The cache function takes the TTL as its second parameter and passes it to the Redis set call with an expiry in seconds. The route handler then supplies 120 explicitly for the user route and again for the map route, and the value becomes visible where the route is declared.
Two details matter here. The cache key for the map routes is a fixed prefix, map route, which the controller later narrows by request parameters. And the rate limit for the map endpoints moved from 100 requests to 1000, which is a router setting rather than a cache setting.
What the findPlace and getDirections endpoints must validate
The directions endpoint must require two query parameters, an origin place ID and a destination place ID, and the places endpoint must require one text query. Because Fastify validates against a route schema, the schema, not the handler, decides whether a request reaches the controller.
A 400 during testing traced back to a copied schema. The places route had inherited the required list for origin and destination while the controller only read a text field, so Fastify rejected every request before the handler ran. Correcting the required array to just the text field fixed it on the next build.
The same mismatch is easy to repeat in any project that duplicates a schema folder. Copying a controller, factory, schema and route is faster than writing four files from scratch, but the search-and-replace has to reach the validation block, not only the class names.
Fastify route schema versus Express and Next.js validation
Fastify validates request and response shapes against a route schema and removes fields outside it, so the handler receives clean input. Fastify ships this at the framework level, in contrast to Express, which needs separate middleware for the same job.
Dev Doido draws the comparison on camera and puts Fastify above Next.js for this particular behavior, while noting that Next.js can add schema handling through its own tooling. That is a speaker opinion from a teaching session, not a measured comparison of the two frameworks.
The practical consequence is that a wrong schema fails loudly. A field the handler reads but the schema rejects produces a 400 with no business logic executed, which is how the required-array bug surfaced in minutes instead of after a live deployment.
Where the upsert and array push belong in the route repository
The route repository needs an upsert so a driver's position updates append to an existing coordinate array instead of creating a new ride document. The MongoDB operator is $push inside a findOneAndUpdate call with upsert: true and returnDocument set to return the modified document.
Two repository changes came with it. An abstract count method returns how many rides exist, and the upsert method takes a query, a data payload and a push payload so any array field can be appended, not only coordinates. The repository keeps these as generic methods on the abstract class.
The duration field also had to be added to the ride record. Without it the stored route is missing how long the trip takes, which the tracking flow needs later. The lesson notes that the field was omitted in the previous session and is being added now.
What the demo proved and what it left open
The demo proved that a repeated directions call returns from Redis and that a place query stores its candidate list under the map route key. The console showed cache writes for both the user route and the map routes after the TTL change.
The place search returned candidates only from Uberlândia, the speaker's city. The library behind the place lookup needs configuration the session did not complete, and the video sets that as an exercise for viewers. Location bias is a real part of the Places API, so a default region is worth setting before the feature ships.
This article was produced from a 2023 tutorial recording published on 2023-10-13. Google Maps billing rules and the Redis Node client's current API are outside what the session covers, so check the current pricing page and client documentation before you size a budget from this walkthrough.
FAQ
- How does Redis reduce Google Maps API costs in a Node.js API? Every route or place lookup that returns from Redis skips the billable Google Maps request. A short TTL covers the repeat views that happen during a single user session without storing stale data for long.
- What should the Redis cache key contain for map lookups? The key should include the endpoint type and the request parameters that change the answer, such as origin and destination place IDs. A fixed prefix alone returns the wrong route for a different pair of coordinates.
- Why pass the TTL as a parameter instead of hard-coding 120 seconds? Different endpoints tolerate different staleness, and a hard-coded value forces every route to share one policy. Passing the value from the route keeps the decision next to the handler that owns it.
- Why did the findPlace endpoint return a 400 during testing? The copied Fastify schema still required origin and destination while the controller only read a text field. Fastify rejected the request at validation, before the handler ran, and correcting the required array fixed it.
- Does the cache layer make the Google Maps adapter unnecessary? No. The adapter is still the only path to Google. The cache sits in front of it and returns early on a hit, so the adapter call remains the fallback.
- Is Fastify a drop-in replacement for Express in this setup? No. Fastify's route schema validation is native, while Express requires separate middleware, so handlers written for Express need changes to benefit from it.
- What MongoDB operator appends driver coordinates to an existing ride? The
$pushoperator inside afindOneAndUpdatecall adds a coordinate to an array field. Settingupsert: truecreates the document when no matching record exists.
- Can the same cache middleware serve the user routes and the map routes? Yes, once the TTL is a parameter and each route declares its own key prefix. The middleware itself does not need to know which domain it serves.
- Where can I learn the full project structure shown in the video? The walkthrough is part of the CrazyStack TypeScript course, and crazystack.com.br lists the complete series covering Fastify, Clean Architecture and MongoDB.
- What is the known limitation left at the end of the session? Place search results stayed inside one city because the places library needs region or location bias configuration. The video leaves that configuration as a task for the viewer.
Turning a recorded walkthrough into something searchable
The useful part of this lesson is not the boilerplate. It is the order of decisions: expose the endpoint, cache the expensive call, pass the policy in from the route, and let validation catch the copy-paste error before a user does. That order is what a written reference preserves.
If your own videos carry lessons like these, the same material can live as an article. Paste a YouTube URL into Skala Blog, let it transcribe the video, and generate a structured draft you can edit before publishing.