---
title: "Caching — Google Places for Laravel | Roundly"
description: "Opt-in caching of idempotent lookups to cut latency and Google spend — safe keys, remembered not-founds and a fresh flag to refresh on demand."
url: https://roundly-consulting.com/open-source/docs/google-places-for-laravel/caching
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Google Places for Laravel](https://roundly-consulting.com/open-source/docs/google-places-for-laravel.md)

# Caching

Set GOOGLE\_PLACES\_CACHE=true to cache idempotent lookups (details, geocode, forward geocode, distance, distance matrix, text & nearby search). Autocomplete is never cached. Cache keys never contain the API key:

```bash
GOOGLE_PLACES_CACHE=true
GOOGLE_PLACES_CACHE_STORE=redis   # optional; null = the default store
GOOGLE_PLACES_CACHE_TTL=86400     # seconds
```

- Cached: details(), geocode(), geocodeAddress(), textSearch(), nearbySearch(), findPlace() (it runs a text search), distance(), computeMatrix() and matrix().
- Not cached: autocomplete(), the paginated helpers textSearchPaginated() / nearbySearchPaginated(), photo requests (photo(), photoUri(), photoContents()) and check().
- A details 404 is an answer — “no such place” — and is cached like any other result, so repeats are not re-billed.
- Transient failures always throw and are never cached.
- The package caches Google’s raw payload and rebuilds the DTOs on read, so entries work with Laravel’s cache.serializable\_classes restriction.
- Cache hits make no request, so they dispatch no lifecycle event.

## Bypassing the cache

Every cached query takes a fresh flag — a trailing constructor argument (fresh: true) or the fresh() wither, which every fluent method keeps; the matrix() handle has its own fresh(). A fresh lookup skips the cache read, asks Google and writes the answer back to the same key:

```php
use RoundlyConsulting\GooglePlaces\DataTransferObjects\DetailsQuery;
use RoundlyConsulting\GooglePlaces\Facades\GooglePlaces;

$place = GooglePlaces::details(new DetailsQuery($placeId, fresh: true));
$place = GooglePlaces::details((new DetailsQuery($placeId))->fresh());   // the same

GooglePlaces::matrix($origins, $destinations)->fresh()->driving();
```

- Write-through — the next plain read gets the refreshed payload, and the entry’s TTL starts again.
- A details 404 — a fresh one stores null, like a plain one, so later plain reads return null.
- Failure — a fresh call that fails throws a PlacesException. Failures are never cached, so the old entry stays in place and plain reads keep getting it.
- A real request — a fresh call takes a rate-limit slot, dispatches PlacesResponseReceived or PlacesRequestFailed and is logged like a miss.
- Cache off — with cache.enabled false every call goes to Google anyway, so the flag changes nothing.
- Off the wire — the flag is never sent to Google and is not part of the cache key, so a fresh call and a plain call share one entry.

| Cached call | Carries the flag |
| --- | --- |
| `details()` | `DetailsQuery` |
| `geocode()` | `ReverseGeocodingQuery` |
| `geocodeAddress()` | `GeocodingQuery` |
| `textSearch()` | `TextSearchQuery` |
| `nearbySearch()` | `NearbySearchQuery` |
| `distance()` | `DistanceQuery` |
| `computeMatrix() / matrix()` | `MatrixQuery / PendingMatrix::fresh()` |

A details() call inside a billing session keeps the flag too. The string and Location shortcuts (details('ChIJ…'), geocode($lat, $lng)) and findPlace() take no flag — pass the query object instead. Endpoints that are never cached have no flag: there is nothing to bypass.

```php
use RoundlyConsulting\GooglePlaces\DataTransferObjects\TextSearchQuery;

// findPlace() takes no flag — run its one-result text search fresh instead:
$place = GooglePlaces::textSearch((new TextSearchQuery('Googleplex'))->take(1)->fresh())->first();
```

## Google’s 30-day limit on stored content

Google’s Maps Platform terms cap how long you may keep Places content: at most 30 consecutive days for what may be stored at all (place IDs are exempt). The terms change, so check Google’s current Maps Service Specific Terms for your use. Two things follow:

- Keep cache.ttl well below 30 days. The package does not cap it.
- If you store snapshots yourself (a places table, for example), refresh them with a fresh lookup. A plain lookup can return a cached payload that is already up to cache.ttl old, so the snapshot you stamp as “refreshed now” would really be older.

## Clearing

Entries expire after cache.ttl. To refresh one entry, repeat its lookup with fresh. There is no package command to flush them all — clear the store, or use a dedicated one via GOOGLE\_PLACES\_CACHE\_STORE, when you need a clean slate.

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/google-places-for-laravel.md)
