Nos últimos dezoito meses o Google descontinuou quatro partes muito usadas da Maps JavaScript API. Duas delas, a Heatmap Layer e a Drawing Library, estão indisponíveis desde maio de 2026. As outras duas, DirectionsService e DistanceMatrixService, são Legacy e estão descontinuadas, mas ainda funcionam e não têm data de desligamento.
Este guia mostra o status atual de cada uma, com links para as páginas do próprio Google, e explica como substituí-las. Quando o substituto é do MapAtlas, o código usa nossos endpoints e formatos de resposta reais.
O que foi descontinuado e o que ainda funciona
| Serviço | Status | Datas principais | Substituto do Google |
|---|---|---|---|
| Heatmap Layer | Removido | Descontinuado em 27 de maio de 2025, desativado na versão 3.65.1c (20 de maio de 2026) | Bibliotecas de terceiros como o deck.gl |
| Drawing Library (DrawingManager) | Removido | Descontinuado em agosto de 2025, indisponível desde maio de 2026 (confirmado na versão 3.65.3b, 4 de junho de 2026) | Bibliotecas de terceiros como o Terra Draw |
| DirectionsService | Legacy, descontinuado | Legacy desde 1º de março de 2025, descontinuado desde 25 de fevereiro de 2026 (versão 3.64.2b), sem data de desligamento | Classe Route da biblioteca Routes |
| DistanceMatrixService | Legacy, descontinuado | Legacy desde 1º de março de 2025, descontinuado desde 25 de fevereiro de 2026 (versão 3.64.2b), sem data de desligamento | Classe RouteMatrix da biblioteca Routes |
Fontes: descontinuações da Google Maps Platform, as notas de versão da Maps JavaScript API e a página de produtos Legacy.
Legacy tem um significado específico. Segundo o Google, um serviço Legacy não recebe novos recursos e não pode ser ativado em novos projetos do Cloud, mas continua com suporte nos projetos existentes. O Google se compromete a avisar com pelo menos 12 meses de antecedência antes de desativá-lo, e a nota de versão que descontinuou DirectionsService e DistanceMatrixService diz que não há desativação programada e que regressões graves ainda serão corrigidas. A mesma mudança para Legacy em 1º de março de 2025 afetou os serviços web Directions API e Distance Matrix API, a Places API e o JavaScript Places Service.
O que quebra
Este código falha hoje nas versões atuais da Maps JavaScript API:
// Removed in 2026: these constructors no longer work
const heatmap = new google.maps.visualization.HeatmapLayer({ data: points });
const drawingManager = new google.maps.drawing.DrawingManager();
Este código ainda roda em projetos existentes, mas está descontinuado e não funciona em um novo projeto do Cloud:
// Legacy and deprecated, no shutdown date yet
const directionsService = new google.maps.DirectionsService();
const distanceMatrixService = new google.maps.DistanceMatrixService();
Se um mapa de calor ou uma ferramenta de desenho do seu site parou de funcionar em maio de 2026, esta é a causa. Corrija isso primeiro. Depois planeje a migração do roteamento, antes que o Google anuncie uma data.
Os substitutos do Google
Para roteamento, o Google oferece dois caminhos, e nenhum obriga você a levar a lógica para um servidor:
- No navegador: a biblioteca Routes da Maps JavaScript API. A classe
Routesubstitui o DirectionsService e a classeRouteMatrixsubstitui o DistanceMatrixService. - Em um servidor: a Routes API, um serviço REST com os métodos Compute Routes e Compute Route Matrix.
Para visualização, o Google não oferece mais uma opção própria. A página do mapa de calor aponta para o deck.gl, e a página de descontinuações cita o Terra Draw para desenho.
Checklist de migração
1. Audite seu código
Procure as classes afetadas:
# Find all files using deprecated Google Maps services
grep -rn "DirectionsService\|DistanceMatrixService\|DirectionsRenderer\|HeatmapLayer\|DrawingManager" \
--include="*.js" --include="*.ts" --include="*.tsx" --include="*.jsx" src/
Registre cada arquivo e componente que as usa, e se cada chamada roda no navegador ou em um servidor.
2. Documente como você usa cada serviço
Para cada uso, anote:
- Modos de transporte (carro, a pé, bicicleta, transporte público)
- Pontos intermediários (simples de A a B ou rotas com várias paradas)
- Campos da resposta que você lê (distância, duração, polilinha, etapas, tarifa)
- Volume (requisições por dia e por mês, para estimar custos)
- Requisitos de latência (tempo real para o usuário ou processamento em lote)
3. Escolha o destino
Opção A: continuar com o Google. Migre para as classes Route e RouteMatrix ou para a Routes API. Compare os campos que você usa com os guias de migração, porque os formatos de resposta são diferentes dos das classes Legacy.
Opção B: trocar de provedor. Você vai reescrever a integração de qualquer forma, então compare provedores com base nos requisitos do passo 2.
4. Rode o antigo e o novo em paralelo
Não migre no lugar. Rode as duas implementações lado a lado por um período e compare distância, duração e latência nas suas rotas reais antes de trocar.
5. Atualize o tratamento de erros
As classes Legacy informavam erros por um valor de status em um callback. Os substitutos REST retornam códigos de status HTTP e corpos de erro, então o tratamento de erros precisa mudar.
Substituindo cada serviço pelo MapAtlas
Os endpoints de roteamento do MapAtlas são serviços REST em gateway.mapmetrics-atlas.net, documentados na documentação da API do MapAtlas. Eles recebem um token como parâmetro de consulta, então chame-os do seu backend.
De DirectionsService para a Directions API do MapAtlas
Antes (Google, Legacy):
const directionsService = new google.maps.DirectionsService();
directionsService.route(
{
origin: { lat: 52.52, lng: 13.405 },
destination: { lat: 48.8566, lng: 2.3522 },
travelMode: google.maps.TravelMode.DRIVING,
waypoints: [
{ location: { lat: 50.9375, lng: 6.9603 }, stopover: true }
],
},
(result, status) => {
if (status === "OK") {
const route = result.routes[0];
console.log("Distance:", route.legs[0].distance.text);
console.log("Duration:", route.legs[0].duration.text);
}
}
);
Depois (Directions API do MapAtlas):
const response = await fetch(
`https://gateway.mapmetrics-atlas.net/directions/?token=${process.env.MAPATLAS_API_KEY}`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
// Ordered stops: origin, waypoints, destination
locations: [
{ lat: 52.52, lon: 13.405 },
{ lat: 50.9375, lon: 6.9603 },
{ lat: 48.8566, lon: 2.3522 },
],
costing: "auto", // auto, bicycle, pedestrian, bus, truck, taxi, motor_scooter
units: "kilometers",
}),
}
);
const { trip } = await response.json();
console.log("Distance (km):", trip.summary.length);
console.log("Duration (s):", trip.summary.time);
// Each leg carries its geometry as an encoded polyline (precision 6)
const shapes = trip.legs.map((leg) => leg.shape);
Principais diferenças:
- Chamada REST em vez de uma classe JavaScript, feita a partir do seu backend.
- Pontos intermediários são as entradas do meio de
locations. - Formato de resposta diferente. Os totais ficam em
trip.summarye cada trecho tem uma polilinha codificada emshape. Decodifique-a antes de desenhar a rota (veja o exemplo de backend mais abaixo).
De DistanceMatrixService para a Matrix API do MapAtlas
A Matrix API do MapAtlas retorna tempo de viagem e distância para cada par de origem e destino em uma única chamada. Nosso endpoint limita cada par a 400 km de distância de rota, por isso o exemplo usa lugares em volta de Berlim.
Antes (Google, Legacy):
const service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [
{ lat: 52.52, lng: 13.405 },
{ lat: 52.3906, lng: 13.0645 },
],
destinations: [
{ lat: 51.3397, lng: 12.3731 },
{ lat: 51.0504, lng: 13.7373 },
],
travelMode: google.maps.TravelMode.DRIVING,
},
(response, status) => {
if (status === "OK") {
response.rows.forEach((row, i) => {
row.elements.forEach((element, j) => {
console.log(`Origin ${i} -> Dest ${j}:`,
element.distance.text, element.duration.text);
});
});
}
}
);
Depois (Matrix API do MapAtlas):
const response = await fetch(
`https://gateway.mapmetrics-atlas.net/matrix/?token=${process.env.MAPATLAS_API_KEY}`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
sources: [
{ lat: 52.52, lon: 13.405 },
{ lat: 52.3906, lon: 13.0645 },
],
targets: [
{ lat: 51.3397, lon: 12.3731 },
{ lat: 51.0504, lon: 13.7373 },
],
costing: "auto",
units: "kilometers",
}),
}
);
const data = await response.json();
// One row per source, one cell per target
data.sources_to_targets.forEach((row: any[], i: number) => {
row.forEach((cell, j) => {
console.log(`Origin ${i} -> Dest ${j}:`, cell.distance, "km", cell.time, "s");
});
});
A grade equivale a rows e elements do Google. As distâncias chegam como números na unidade que você pedir e os tempos em segundos, então a formatação fica com você.
Substituto da Heatmap Layer
Opção 1: uma camada de mapa de calor no MapLibre GL JS (código aberto)
import maplibregl from "maplibre-gl";
const map = new maplibregl.Map({
container: "map",
style: "https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_ACCOUNT_ID/mapstyle.json&token=YOUR_API_KEY",
center: [13.405, 52.52],
zoom: 10,
});
map.on("load", () => {
map.addSource("heat-data", {
type: "geojson",
data: {
type: "FeatureCollection",
features: heatmapPoints.map((point) => ({
type: "Feature",
geometry: { type: "Point", coordinates: [point.lng, point.lat] },
properties: { weight: point.weight },
})),
},
});
map.addLayer({
id: "heatmap-layer",
type: "heatmap",
source: "heat-data",
paint: {
"heatmap-weight": ["get", "weight"],
"heatmap-intensity": 1,
"heatmap-radius": 20,
"heatmap-opacity": 0.7,
},
});
});
O mapa de calor é renderizado pela própria biblioteca de mapas, sem serviço extra.
Opção 2: a HeatmapLayer do deck.gl, sugerida pela documentação do Google:
import { HeatmapLayer } from "@deck.gl/aggregation-layers";
const heatmapLayer = new HeatmapLayer({
data: heatmapPoints,
getPosition: (d) => [d.lng, d.lat],
getWeight: (d) => d.weight,
radiusPixels: 30,
});
As duas funcionam. O MapLibre GL JS lê os estilos do MapAtlas diretamente, e o deck.gl pode ficar por cima de qualquer mapa base.
Substituto da Drawing Library
O DrawingManager permitia que usuários desenhassem marcadores, linhas, círculos e polígonos no mapa. O Terra Draw, biblioteca citada pela página de descontinuações do Google, oferece os mesmos modos e tem adaptadores para várias bibliotecas de mapas, incluindo Google Maps e MapLibre GL JS. As formas voltam em GeoJSON, que você pode salvar ou enviar sem alterações para um serviço de geofencing ou de isócronas.
Comparação de custos
Os preços de tabela do Google são os mesmos para os SKUs Legacy de roteamento e para os SKUs Essentials dos substitutos. Todos os preços abaixo vêm da página de preços da Google Maps Platform e da página de preços do MapAtlas, conferidas em 26 de setembro de 2026.
| Serviço | Google, grátis por mês | Google, por 1.000 depois disso (primeira faixa) | MapAtlas, grátis por mês | MapAtlas, por 1.000 depois disso (primeira faixa) |
|---|---|---|---|---|
| Directions (Legacy) ou Compute Routes Essentials | 10.000 | US$ 5,00 | 100.000 requisições de navegação | € 1,53 |
| Directions Advanced (Legacy) ou Compute Routes Pro | 5.000 | US$ 10,00 | Mesma faixa de navegação | € 1,53 |
| Distance Matrix (Legacy) ou Compute Route Matrix Essentials | 10.000 elementos | US$ 5,00 | Veja a página de preços | Veja a página de preços |
| Geocoding | 10.000 | US$ 5,00 | 25.000 | € 3,90 |
O Google cobra em dólares americanos e o MapAtlas em euros, então converta antes de comparar. Os dois aplicam tarifas menores em volumes maiores. Um exemplo com 500.000 requisições de rota por mês:
- Google Compute Routes Essentials: 10.000 grátis, 90.000 a US$ 5,00 e 400.000 a US$ 4,00, ou seja, US$ 2.050.
- Navegação MapAtlas: 100.000 grátis e 400.000 a € 1,53, ou seja, cerca de € 610.
Exemplo completo: rota de backend e mapa
Este padrão mantém a chave de API no servidor e envia ao navegador só a geometria da rota.
Rota de API no backend (Next.js)
// app/api/directions/route.ts
import { NextRequest, NextResponse } from "next/server";
// Decode an encoded polyline with precision 6 into [lon, lat] pairs
function decodePolyline6(str: string): [number, number][] {
const coords: [number, number][] = [];
let index = 0, lat = 0, lng = 0;
while (index < str.length) {
for (const axis of [0, 1]) {
let result = 0, shift = 0, byte: number;
do {
byte = str.charCodeAt(index++) - 63;
result |= (byte & 0x1f) << shift;
shift += 5;
} while (byte >= 0x20);
const delta = result & 1 ? ~(result >> 1) : result >> 1;
if (axis === 0) lat += delta; else lng += delta;
}
coords.push([lng / 1e6, lat / 1e6]);
}
return coords;
}
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const [oLat, oLon] = searchParams.get("origin")!.split(",").map(Number);
const [dLat, dLon] = searchParams.get("destination")!.split(",").map(Number);
const response = await fetch(
`https://gateway.mapmetrics-atlas.net/directions/?token=${process.env.MAPATLAS_API_KEY}`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
locations: [{ lat: oLat, lon: oLon }, { lat: dLat, lon: dLon }],
costing: "auto",
units: "kilometers",
}),
}
);
if (!response.ok) {
return NextResponse.json({ error: "routing failed" }, { status: 502 });
}
const { trip } = await response.json();
const coordinates = trip.legs.flatMap((leg: { shape: string }) => decodePolyline6(leg.shape));
return NextResponse.json({
coordinates,
distanceKm: trip.summary.length,
durationS: trip.summary.time,
});
}
Componente de mapa (React e MapLibre GL JS)
import { useEffect, useRef } from "react";
import maplibregl from "maplibre-gl";
function DirectionsMap({ origin, destination }: {
origin: { lat: number; lng: number };
destination: { lat: number; lng: number };
}) {
const mapRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const map = new maplibregl.Map({
container: mapRef.current!,
style: "https://gateway.mapmetrics-atlas.net/styles/?fileName=YOUR_ACCOUNT_ID/mapstyle.json&token=YOUR_API_KEY",
center: [origin.lng, origin.lat],
zoom: 7,
});
map.on("load", async () => {
const res = await fetch(
"/api/directions?" +
new URLSearchParams({
origin: `${origin.lat},${origin.lng}`,
destination: `${destination.lat},${destination.lng}`,
})
);
if (!res.ok) return;
const { coordinates } = await res.json();
map.addSource("route", {
type: "geojson",
data: {
type: "Feature",
geometry: { type: "LineString", coordinates },
properties: {},
},
});
map.addLayer({
id: "route-line",
type: "line",
source: "route",
paint: { "line-color": "#4A90D9", "line-width": 5 },
});
const bounds = coordinates.reduce(
(b: maplibregl.LngLatBounds, coord: [number, number]) => b.extend(coord),
new maplibregl.LngLatBounds(coordinates[0], coordinates[0])
);
map.fitBounds(bounds, { padding: 50 });
});
return () => map.remove();
}, [origin, destination]);
return <div ref={mapRef} style={{ width: "100%", height: "400px" }} />;
}
Como testar a migração
Passo 1: compare as duas implementações
Durante um período de teste, chame o serviço antigo e o novo com as mesmas requisições. Registre distância e duração dos dois e analise as diferenças nas suas rotas reais, principalmente balsas, pedágios e vias com restrição.
Passo 2: use uma feature flag
Coloque o provedor atrás de uma flag para poder voltar sem um deploy:
const useMapAtlasDirections = process.env.FEATURE_MAPATLAS_DIRECTIONS === "true";
const directions = useMapAtlasDirections
? await fetchMapAtlasDirections(origin, destination)
: await fetchGoogleDirections(origin, destination);
Passo 3: monitore as taxas de erro
Depois da troca, acompanhe:
- Taxas de HTTP 4xx e 5xx da nova API
- Mudanças de latência
- Campos ausentes que a sua interface lê
- Diferenças de rota em casos extremos como balsas, rodovias com pedágio e áreas restritas
Passo 4: teste de carga antes de ir para produção
Se o seu tráfego tem picos, por exemplo no despacho da manhã em uma plataforma de logística, faça um teste de carga da nova API com o dobro do seu volume de pico antes de depender dela.
O que fazer agora
- Se você ainda carrega a Heatmap Layer ou a Drawing Library: substitua-as primeiro. Elas não funcionam mais nas versões atuais da Maps JavaScript API.
- Audite o código de roteamento: encontre cada chamada a DirectionsService, DirectionsRenderer e DistanceMatrixService.
- Escolha o substituto: as classes
RouteeRouteMatrix, a Routes API ou outro provedor. - Migre um serviço por vez, atrás de uma feature flag, e compare os resultados antes da troca.
- Acompanhe a página de descontinuações do Google caso surja uma data de desligamento. O Google se comprometeu com pelo menos 12 meses de aviso para serviços Legacy.
Para testar as APIs de roteamento do MapAtlas, crie uma conta gratuita e leia a documentação da API. Para ajuda com uma migração, use a página de contato.
Perguntas frequentes
A Drawing Library do Google Maps ainda está disponível?
Não. O Google descontinuou a Drawing Library, incluindo o DrawingManager, em agosto de 2025, e a página de descontinuações a lista como indisponível desde maio de 2026. As notas da versão 3.65.3b da Maps JavaScript API (4 de junho de 2026) confirmam que o DrawingManager não está mais disponível. O Google cita o Terra Draw como alternativa.
A Heatmap Layer ainda está disponível?
Não. O Google descontinuou a Heatmap Layer em 27 de maio de 2025, e a versão 3.65.1c de 20 de maio de 2026 informa que ela foi desativada. O Google sugere no lugar bibliotecas de terceiros, como a HeatmapLayer do deck.gl.
Quando DirectionsService e DistanceMatrixService vão parar de funcionar?
O Google não definiu data. Os dois estão em status Legacy desde 1º de março de 2025 e descontinuados desde 25 de fevereiro de 2026. Segundo as notas de versão do Google, não há desativação programada, eles continuam recebendo correções para regressões graves e haverá pelo menos 12 meses de aviso antes do fim do suporte. Serviços Legacy não estão disponíveis para novos projetos do Cloud, então um projeto novo precisa das classes Route e RouteMatrix ou de outro provedor.
Posso migrar aos poucos ou preciso trocar tudo de uma vez?
Você pode migrar um serviço por vez. Cada classe descontinuada é independente. Substitua primeiro a Drawing Library e a Heatmap Layer, que já não funcionam, e depois DirectionsService e DistanceMatrixService no seu próprio ritmo.
O MapAtlas aceita pontos intermediários e vários modos de transporte?
Sim. A Directions API do MapAtlas recebe uma lista ordenada de locais, então cada ponto entre o primeiro e o último é um ponto intermediário, e aceita os modelos de custo auto, bicycle, pedestrian, bus, truck, taxi e motor_scooter. É um endpoint REST, então chame-o do seu backend para a chave de API não chegar ao cliente.

