Skip to content
Products
Solutions
By industry
By use case
Resources
Products
Solutions
By industry
By use case
Resources
Products
Solutions
By industry
By use case
Resources
Google Maps Platform best practices: Optimization and performance tips
Travis McPhail
Engineering Lead, Google Maps Platform
Sep 10, 2019
Try Google Maps Platform
Get $200 usage monthly for no charge. Starting March 1, 2025, build more for free.*
Learn more

Whether we’re talking about desktop browsers or the mobile web, users have come to expect web apps that give them what they want with smooth, fast UI performance. For JavaScript developers, this means optimizing performance becomes one of the biggest concerns. The difference between a site that lags or responds slowly and one that doesn’t is the difference between attracting and retaining users or losing them, and apps that deliver mapping or other location-based features are no exception. Recently I gave a talk on this topic, and I want to recap some of the tips I gave.

Using custom overlaysCustom overlays allow you to render custom geospatial data on top of the map that moves along with the map when the user drags or zooms. We see a lot of developers use this as a way of placing their own data, such as markers, on the maps. This is done in OverlayView.draw():

MyOverlay.prototype = new google.maps.OverlayView();

/** @constructor */
function MyOverlay(map, ...) { ... };

MyOverlay.prototype.draw = function() { ... };
Copied to clipboard!

This is a perfectly good way to build a custom map, but if you’re going to do this, it’s important to know that every time the user pans or zooms the map, we redraw the basemap as well as call your OverlayView.draw() to redraw your overlaid content. This is something you need to take into account if the logic for creating or updating your custom overlays is either compute heavy or blocking, since it can introduce some stuttering or lag into the overall map experience due to your code executing at the same time we are trying to redraw the map. Also, be sure to only execute the code you need in draw(). Anything not needed to actually execute rendering should be done beforehand to keep your call as lightweight as possible.

Here’s an example of a custom overlay that’s overlapping its rendering with the map rendering:

Example custom overlay overlapping its rendering

Another tip: create a better user experience by only adding or removing content when the map is stationary. A good best practice is to take advantage of events such as drag or dragend that will tell you when the user is interacting with the map, so you can avoid making changes to your custom overlays while we are redrawing. The same goes for adding and removing markers from the map.

Here’s what the earlier example looks like when we wait for the user interaction to complete:

Previous example but with user interaction complete

Much better! Not only does the map perform better, you’ll also notice that we improved the user experience by only rendering markers in the view once the user stops panning.

**Using markers**Another way developers can add data to the map while maintaining a performant implementation is through the use of markers. A marker identifies a location on a map. By default, markers added to the map use our standard red pin, but you can also use custom images. Let’s take a look at what a performant use of markers might look like. 

In this example, we have a method that generates 1,000 geocodes within a bounding box:

function initLocations(latMin, lngMin, latMax, lngMax, numPoints) {
  let latExtent = latMax - latMin;
  let lngExtent = lngMax - lngMin;
  let tmpLocations = new Array(numPoints);

  for (let i = 0; i < numPoints; i++) {
    tmpLocations[i] = {
        lat: Math.random() * latExtent + latMin,
        lng: Math.random() * lngExtent + lngMin};
    };
  }
  return tmpLocations;
}
...
let locations = initLocations(-33, 117, -22, 148, 1000);
Copied to clipboard!

Next, we create some markers and add them to the map. Notice that we are specifying a custom .svg for the markers:

function initMap() {
    // initialize the map
    let map = new google.maps.Map(document.getElementById('map'), {
      zoom: 3,
      center: {lat: -25.906174, lng: 132.409812},
    });

    // Add the markers to the map
    let markers = locations.map((location, i) => {
      return new google.maps.Marker({
        icon: './images/pin.svg',
        position: location,
        zIndex: i,
        map: map
      });
    });

    // Add event listeners to the markers
    markers.map((marker, i) => {
      marker.addListener('mouseover', () => {
          toggleIcon(marker, true);
      });
      marker.addListener('mouseout', () => {
          toggleIcon(marker, false);
      });
    });

    ...
  }
Copied to clipboard!

Now take a look at what happens when we interact with the map:

Optimization and performance tips visual 3

Notice how there is lag when we pan and zoom. Now, let’s make a simple change by switching to a raster image (in this case a png) for our markers in the `Icon` property of the code snippet above:

UpdatedGIF

No more lag! Although in many cases svg images perform better on the web, we actually implement special optimizations for rendering custom markers with raster images when a large number (think multiple hundreds) of markers are being rendered all at once. So the takeaway here is to use raster images for better performance if you intend on putting a lot of markers on the map. 

**What else?**This covers just a couple of the things you can do to optimize your usage of the Maps JavaScript API, but there’s always more to be done depending on what’s important to your implementation. For example, marker clustering is a must for maps that display a lot of markers.

For more about the Maps JavaScript API, check out our docs. And if you missed my talk, check out the video to also learn more about what we have planned for Google Maps Platform.

Clay cityscape
Clay cityscape
Get going with Google Maps Platform