Is this number of tile requests for Azure Maps normal for a React application?

I am working on building a Demo for a 3D flight tracker. It’s a React application and I’ve borrowed and stitched together some example code.

I have added an Azure Maps base layer and am using this plugin to integrate it. In a time span of approximately 5 minutes, I racked up about 2.5k api requests and I’m guessing then somewhere close to 30k tiles? Is that correct? Or is my application doing something obviously wrong. Perhaps I’m going about it the wrong way entirely.

import {
  Cartesian3,
  Ion,
  Terrain,
  Viewer,
  JulianDate,
  SampledPositionProperty,
  Color,
  TimeIntervalCollection,
  TimeInterval,
  PathGraphics,
  createOsmBuildingsAsync,
  UrlTemplateImageryProvider,
  Resource,
  Credit,
  ImageryLayer
} from 'cesium';
import React, { useEffect, useRef, useState } from 'react';

window.CESIUM_BASE_URL = '/out/release/Cesium';

const FlightViwer3D = () => {
  const [viewer, setViewer] = useState<any>(undefined);
  const cesiumRef = useRef();
  Ion.defaultAccessToken = 'token token token';
  const flightData = JSON.parse('data data data');

  useEffect(() => {
    setViewer(
      new Viewer('cesiumContainer', {
        terrain: Terrain.fromWorldTerrain(),
        baseLayerPicker: true,
        baseLayer: new ImageryLayer(
          new UrlTemplateImageryProvider({
            url: new Resource({
              url: 'https://atlas.microsoft.com/map/tile?api-version=2.0&zoom={z}&x={x}&y={y}&tileSize=512',
              tileWidth: 512,
              tileHeight: 512,
              queryParameters: {
                //Add your Azure Maps key to the map SDK. Get an Azure Maps key at https://azure.com/maps. NOTE: The primary key should be used as the key.
                'subscription-key': 'primary key from azure maps here',

                /*
                                Tileset ID specifies which data layers to render in the tiles. Can be:

                                'microsoft.base.road',
                                'microsoft.base.darkgrey',
                                'microsoft.imagery', //Only supports tile width/height of 256
                                'microsoft.weather.infrared.main',
                                'microsoft.weather.radar.main',
                                'microsoft.base.hybrid.road',
                                'microsoft.base.labels.road '
                            */
                tilesetId: 'microsoft.base.road',

                //The language of labels. Supported languages: https://docs.microsoft.com/en-us/azure/azure-maps/supported-languages
                language: 'en-US',

                //The regional view of the map. Supported views: https://aka.ms/AzureMapsLocalizationViews
                view: 'Auto'
              }
            }),
            credit: new Credit(
              `© ${new Date().getFullYear()} TomTom, Microsoft`,
              true
            ),
            maximumLevel: 12,
            enablePickFeatures: false
          })
        )
      })
    );
  }, [cesiumRef.current]);

  useEffect(() => {
    const someFunc = async () => {
      if (viewer) {
        // Add Cesium OSM Buildings, a global 3D buildings layer.
        const buildingTileset = await createOsmBuildingsAsync();
        viewer.scene.primitives.add(buildingTileset);
        const timeStepInSeconds = 30;
        const totalSeconds = timeStepInSeconds * (flightData.length - 1);
        const start = JulianDate.fromIso8601('2020-03-09T23:10:00Z');
        const stop = JulianDate.addSeconds(
          start,
          totalSeconds,
          new JulianDate()
        );
        viewer.clock.startTime = start.clone();
        viewer.clock.stopTime = stop.clone();
        viewer.clock.currentTime = start.clone();
        viewer.timeline.zoomTo(start, stop);
        // Speed up the playback speed 50x.
        viewer.clock.multiplier = 50;
        // Start playing the scene.
        viewer.clock.shouldAnimate = true;

        // The SampledPositionedProperty stores the position and timestamp for each sample along the radar sample series.
        const positionProperty = new SampledPositionProperty();

        for (let i = 0; i < flightData.length; i++) {
          const dataPoint = flightData[i];

          // Declare the time for this individual sample and store it in a new JulianDate instance.
          const time = JulianDate.addSeconds(
            start,
            i * timeStepInSeconds,
            new JulianDate()
          );
          const position = Cartesian3.fromDegrees(
            dataPoint.longitude,
            dataPoint.latitude,
            dataPoint.height
          );
          // Store the position along with its timestamp.
          // Here we add the positions all upfront, but these can be added at run-time as samples are received from a server.
          positionProperty.addSample(time, position);

          viewer.entities.add({
            description: `Location: (${dataPoint.longitude}, ${dataPoint.latitude}, ${dataPoint.height})`,
            position: position,
            point: { pixelSize: 10, color: Color.RED }
          });
        }

        const airplaneEntity = viewer.entities.add({
          availability: new TimeIntervalCollection([
            new TimeInterval({ start: start, stop: stop })
          ]),
          position: positionProperty,
          point: { pixelSize: 30, color: Color.GREEN },
          path: new PathGraphics({ width: 3 })
        });
        viewer.trackedEntity = airplaneEntity;
      }
    };
    someFunc();
  }, [viewer]);

  return (
    <div
      ref={cesiumRef}
      id="cesiumContainer"
      style={{
        position: 'relative',
        width: '100%',
        minWidth: '290px',
        height: '600px'
      }}
    ></div>
  );
};

export default FlightViwer3D;

Hi @adrocic,

Are you concerned specifically with the number of Azure Map tiles, or the number of requests in general?

I’m not familiar with this particular plugin, but the number of tile requests is going to be dependent on how the camera is moving around the scene. If the camera is very zoomed in, the application will load several level of tiles. If the camera is moving to different areas throughout the scene, new tiles will needed to be loaded.

Well, the team and I are mostly concerned about the number of requests being so high for such minimal usage. Azure charges quite a steep price for tiles requested. After having done some more testing and more research though, it does seem that the number of requests I was seeing was indeed correct. I do have more questions now about how Cesium offers different providers and how that’s all priced, because the pricing guide is sort of confusing between what Cesium declares and what the providers (google, azure, arcgis) claim on their respective pricing guides. I did put in a contact request with the Sales team though and hopefully they can answer more questions. Thanks for the response!