Overcoming Geocoding Limits: How to Manage the OVER_QUERY_LIMIT Status

Everything you need to know when going beyond the Google Geocoding API rate limit

JSFiddle shows OVER_QUERY_LIMIT geocode error
JSFiddle shows OVER_QUERY_LIMIT geocode error

Have you ever encountered a frustrating moment when your application suddenly stopped working because Google's geocoder.geocode() function returns the "OVER_QUERY_LIMIT" status?

This status is triggered when too many requests are sent to the geocoding service within a short time, exceeding the Google Geocoding API rate limit. It is designed to prevent service abuse and ensure the smooth operation of the service for all users.

By following the tips and techniques outlined in this guide, you'll be able to efficiently manage this status and keep your geocoding-based projects on track. We also introduce you to Geoapify's Geocoding API, a Google Geocoding alternative, that lets you avoid the rate-limiting problems associated with using Google's service.

Understanding the Google Geocoding API Rate Limit

When using the Google Geocoding API, it's essential to understand the rate limit to avoid exceeding the maximum number of requests allowed within a specific time frame.

It's important to mention that the "OVER_QUERY_LIMIT" status may occur in two scenarios:

  • The first scenario is when you exceed the daily quota or usage limits set for your project or run out of credits. Please note that if you have yet to create and attach a billing account to your project, your Maps Platform APIs might be limited to 1 request per day.

  • The second scenario is when you exceed the maximum queries per second (QPS) limit set for the Google Maps Platform product you are using. According to Google Maps API documentation, the Geocoding API has a rate limit of 50 requests per second, which translates to a maximum of one request every 20 milliseconds.

If you continue to exceed the limit, your API access may be temporarily blocked to prevent service abuse and ensure a stable service for other users. Therefore, it's crucial to manage your QPS usage carefully and optimize your application to prevent QPS overages.

Methods to Avoid Exceeding the Rate Limit

There are several actions you can take to fix the issue. Here are some of them:

Add delays when geocoding a large number of addresses

Adding delays in your code when geocoding a large number of addresses is one of the most effective methods for avoiding the "OVER_QUERY_LIMIT" status. This approach can help optimize your API usage and avoid triggering the rate limit error.

Here is a JavaScript code example that demonstrates how to do this:

function initMap() {
  const map = new google.maps.Map(document.getElementById('map'), {
    zoom: 8,
    center: {
      lat: 42.508220,
      lng: -71.060125
    }
  });
  const geocoder = new google.maps.Geocoder();
  const bounds = new google.maps.LatLngBounds();

  geocodeAddressesWithDelay(geocoder, map, bounds);
}

const addresses = [... /* your addresses here */];

function geocodeAddress(address, geocoder, map, bounds) {
  return new Promise((resolve, reject) => {
    geocoder.geocode({
      'address': address
    }, (results, status) => {
      if (status === 'OK') {
        resolve(results);
      } else {
        reject(status)
      }
    });
  })
}

function geocodeAddressesWithDelay(geocoder, map, bounds) {
  let i = 0;
  const delay = 100; // 100 ms
  
  
  const intervalId = setInterval(() => {
    if (i >= addresses.length) {
      clearInterval(intervalId);
      return;
    }
    geocodeAddress(addresses[i], geocoder)
      .then((geocodingResults) => {
      	console.log(geocodingResults[0]);
        
        bounds.extend(geocodingResults[0].geometry.location);
        
        var marker = new google.maps.Marker({
          map: map,
          position: geocodingResults[0].geometry.location
        });
        map.fitBounds(bounds);
      })
      .catch((error) => {
        console.error(`Failed to geocode ${addresses[i]}: ${error}`);
      });
    i++;
  }, delay);
}

In this code, the geocodeAddress() function is used to geocode a single address by sending a request to the Google Geocoding API. The function returns a promise that resolves to the location of the address if the geocoding is successful, or rejects with an error status if the geocoding fails.

The geocodeAddressesWithDelay() function is used to geocode an array of addresses with delays in between the requests to avoid rate limits. The function uses a setInterval function to call the geocodeAddress function for each address in the array, with a delay of 100 milliseconds between each request. The delay can be adjusted based on the specific rate limit and requirements.

When a location is successfully geocoded, the function logs the latitude and longitude of the location to the console and adds a map marker. If there is an error, the function logs the error status to the console.

Recap failing requests

Implementing error handling and recapping failing requests is another way to avoid the "OVER_QUERY_LIMIT" status. For example, you can implement a retry mechanism to resend requests that fail due to rate limits.

This is a JavaScript code that shows how to use the Google Maps Geocoding API to geocode an array of addresses, while also implementing rate limiting and retrying for failed requests:

const addresses = [... /* your addresses here */];

const geocoder = new google.maps.Geocoder();
const retryDelay = 1000;
const maxRetryCount = 5;
let retryCount = 0;

geocodeAddresses(addresses, geocoder);

function geocodeAddress(address, geocoder) {
  return new Promise((resolve, reject) => {
    geocoder.geocode({ address: address }, (results, status) => {
      if (status === 'OK') {
        resolve(results[0]);
      } else if (status === 'OVER_QUERY_LIMIT') {
        // If rate limit is exceeded, wait and try again
        setTimeout(() => {
          retryCount++;
          if (retryCount <= maxRetryCount) {
            geocodeAddress(address, geocoder).then(resolve).catch(reject);
          } else {
            reject(new Error(`Geocoding failed after ${maxRetryCount} attempts: ${address}`));
          }
        }, retryDelay);
      } else {
        reject(new Error(`Geocoding failed: ${address} (${status})`));
      }
    });
  });
}

async function geocodeAddresses(addresses, geocoder) {
  let results = [];
  for (let i = 0; i < addresses.length; i++) {
    retryCount = 0; // Reset retry count for geocoding request
    try {
      const result = await geocodeAddress(addresses[i], geocoder);
      results.push(result);
    } catch (error) {
      console.error(error.message);
    }
    
  }
  console.log(results);
}

The `geocodeAddress`` function takes an individual address and the Google's Geocoder instance, and returns a Promise that resolves with the geocoding result for that address:

  • If the geocoding status is "OK", the Promise is resolved with the first result in the results array.
  • If the status is "OVER_QUERY_LIMIT", the function will wait for the retry delay, and then try again up to the maximum retry count.
  • If the status is anything else, the Promise is rejected with an error message.

Recapping failed geocoding requests can effectively handle "OVER_QUERY_LIMIT" errors, but it should be used with caution. We recommend using this method only when geocoding is triggered by user action and the number of addresses is relatively small.

Manage your billing and usage metrics carefully

You can keep track of your API usage and ensure that you are staying within your quotas and usage limits. This can help you avoid unexpected service disruptions and enable you to optimize your usage to better suit your needs.

To monitor the usage of individual APIs in the Google Cloud Console, follow these steps:

  • Select the project that contains the API you want to review.
  • From the Dashboard's list of APIs, click on the name of the API you wish to monitor.
  • Near the top of the page, click on the Metrics or Quotas tab to view detailed usage statistics.

It is strongly recommended to set daily API usage limits to avoid unexpected high costs. By setting daily usage limits, you can have better control over your usage and avoid overage charges resulting from excessive use.

Google Cloud Console also provides alerting and reporting features that can help you stay informed about your Maps Platform APIs usage and notify you when you are approaching your usage limits.

Why is caching not an option?

The Google Maps Platform Terms of Service specify that caching of geocoding results is generally not allowed. Specifically, the policy states that:

"Customer can temporarily cache latitude (lat) and longitude (lng) values from the Geocoding API for up to 30 consecutive calendar days, after which Customer must delete the cached latitude and longitude values. Customer can cache Geocoding API Place ID (place_id) values, in accordance with the Geocoding API Policies."

So caching geocoding results is not compliant with the Google Maps Platform Terms of Service and not allowed. If you need to cache and store geocoding results, you will need to choose alternative solutions that are compliant with the API policy.

Another Problem with Google's Geocoding API: Cost

However, there's another problem that many developers confront when using Google's Geocoding API - it's prohibitively expensive!

Google provides a free tier ($200 in compensation) for the Google Maps Platform that allows for up to 40,000 geocoding requests per month, which averages out to around 1,333 requests per day. If your application falls within this usage limit, you can use the geocoding service for free without incurring any charges. But, afterward, the cost of employing the API can quickly escalate, particularly if you need to make a considerable number of requests.

Here are some cost examples, according to Google's Platform Pricing:

RequestsMonthly cost
50,000$50
100,000$300
250,000$900

So, what's the ultimate solution?

Geoapify: A More Affordable and Dependable Alternative

Check Geoapify Geocoding API, a more budget-friendly and dependable alternative to Google's Geocoding API. Geoapify offers a vast array of features at a minuscule fraction of the cost, so you won't have to concern yourself with surpassing the rate limit and frustrating your users.

  • We have "soft" limits. This means a usage limit that is not strictly enforced by the API service but is instead intended to serve as a guideline or recommendation for best practices. Soft limits are often put in place to encourage responsible usage of the API service and to ensure that the service is available to all users.
  • We do not block customers. It is generally not in our best interest to block paying customers who exceed these limits. Instead, many we will contact the customer to discuss their usage patterns and explore potential solutions, such as upgrading to a higher-tier plan or implementing optimizations to reduce the number of API requests.
  • We offer open data. That means you can cache, store and redistribute the addresses, structured addresses, and coordinates without restrictions.

Additionally, our transparent and straightforward pricing model guarantees that you'll never be surprised by any hidden charges or fees.

For example, here's what you'd pay for the usage volumes above with Geoapify Geocoding:

  • Up to 90,000 requests per month (or 3,000 / day) are Free
  • Up to 300,000 requests per month (or 10,000 / day) are 49€ / month
  • Up to 750,000 requests per month (or 25,000 / day) are 89€ / month

Conclusion

In conclusion, exceeding the Google Geocoding API rate limit is a minor roadblock that can easily be overcome. But, if you're looking for a more affordable and reliable alternative, consider Geoapify. You can find all the pricing information you need here.

So, go ahead and make the most of the Geocoding API to create amazing location-based services and never let a rate limit or high cost stop you again!