Google планомерно ужесточает требования своей Maps Platform на протяжении нескольких лет, но волна устареваний мая 2026 года оказывается наиболее разрушительной из всех предшествующих. Из Maps JavaScript API удаляются четыре широко используемые возможности: Heatmap Layer, Drawing Library, DirectionsService и DistanceMatrixService. Если приложение опирается на любую из них, времени на миграцию осталось совсем немного.
Речь не о мягком устаревании, при котором старые endpoints продолжают работать годами. Google установил жёсткие даты удаления, и консоль разработчика уже отображает соответствующие предупреждения. Данное руководство охватывает конкретные изменения, их причины и способы миграции каждого сервиса с рабочими примерами кода. Для тех, кто ищет готовую замену, здесь показано, как API MapAtlas соответствует каждому устаревшему сервису Google.
Что и когда устаревает
Полная хронология затронутых сервисов:
| Сервис | Объявлен устаревшим | Дата удаления | Замена (Google) |
|---|---|---|---|
| Heatmap Layer (Maps JS API) | Август 2025 | Май 2026 | Maps Datasets API + deck.gl |
| Drawing Library (Maps JS API) | Май 2025 | Май 2026 | Extended Component Library |
| DirectionsService (Maps JS API) | 25 февраля 2026 | Май 2026 | Routes API (REST) |
| DistanceMatrixService (Maps JS API) | 25 февраля 2026 | Май 2026 | Routes API (REST) |
Принципиальный момент: Google не устраняет маршрутизацию и расчёт расстояний как таковые. Удаляются JavaScript-классы на стороне клиента, которыми разработчики пользуются более десяти лет, а взамен предлагается миграция на новый Routes API — серверный REST-endpoint. Это не банальная смена версии, а архитектурное изменение, перемещающее логику маршрутизации из браузера в бэкенд.
Что перестанет работать
Если в кодовой базе присутствует любой из следующих фрагментов, после даты удаления он будет выбрасывать ошибку:
// All of these will stop working in May 2026
const directionsService = new google.maps.DirectionsService();
const distanceMatrixService = new google.maps.DistanceMatrixService();
const heatmap = new google.maps.visualization.HeatmapLayer({ data: points });
const drawingManager = new google.maps.drawing.DrawingManager();
После удаления эти конструкторы будут генерировать исключения. Никакого fallback-поведения, никакой плавной деградации. Карта загрузится, однако любая функциональность, зависящая от этих классов, полностью перестанет работать.
Почему Google вводит эти изменения принудительно
Официальная позиция Google — производительность и модернизация. Routes API, пришедший на смену DirectionsService и DistanceMatrixService, поддерживает новые возможности: экологичную маршрутизацию, маршрутизацию для двухколёсных транспортных средств и расчёт стоимости платных дорог, которые устаревшие JavaScript-классы не могут обеспечить.
Реальным движущим фактором является ценовой контроль. Перенос маршрутизации на серверный REST API даёт Google более детальный биллинг и точное отслеживание использования. JavaScript-вариант DirectionsService позволял реализовывать клиентские паттерны пакетной обработки, которые Google сложнее было точно тарифицировать. Routes API гарантирует, что каждый запрос проходит через измеряемый endpoint.
В случае Heatmap Layer и Drawing Library Google подталкивает разработчиков к собственной Extended Component Library и сторонним инструментам визуализации, в частности deck.gl. Это проявление более широкой тенденции: Google сохраняет за собой рендеринг тайлов карты, а всё остальное передаёт экосистеме.
Практические последствия для разработчиков: бо́льшая серверная инфраструктура, больше API-ключей под управлением и, как правило, более высокая стоимость запросов на новых ценовых уровнях.
Чек-лист миграции
Прежде чем писать какой-либо код миграции, следует проработать этот чек-лист:
1. Проведите аудит кодовой базы
Выполните поиск по всей кодовой базе на предмет обращений к устаревшим классам:
# Find all files using deprecated Google Maps services
grep -rn "DirectionsService\|DistanceMatrixService\|HeatmapLayer\|visualization.HeatmapLayer\|drawing.DrawingManager\|DrawingManager" \
--include="*.js" --include="*.ts" --include="*.tsx" --include="*.jsx" src/
Задокументируйте каждый файл и компонент, использующий эти сервисы. Зафиксируйте, происходят ли вызовы на стороне клиента (браузер) или в серверном контексте (например, API routes в Next.js).
2. Определите паттерны использования
Для каждого случая использования задокументируйте:
- Применяемые режимы передвижения (driving, walking, cycling, transit)
- Поддержка waypoints (простой маршрут A-B или многоточечные маршруты)
- Используемые поля ответа (расстояние, время, polyline, шаги, тариф)
- Объём (запросы в день/месяц, для оценки стоимости)
- Требования к задержке (real-time для конечного пользователя или пакетная обработка)
3. Выберите целевой вариант миграции
Доступны два варианта:
Вариант A: Остаться с Google. Перейти с устаревших JavaScript-классов на новый Google Routes API (REST). Это потребует изменений на бэкенде, новых прав доступа для API-ключа и обновления биллинга.
Вариант B: Сменить провайдера. Перейти на сторонний routing API. Поскольку код интеграции всё равно придётся переписывать, это подходящий момент для оценки альтернатив.
4. Настройте параллельную среду
Ни в коем случае не мигрируйте «на месте». Запускайте старую и новую реализации параллельно не менее двух недель, сравнивая результаты по точности и задержке перед окончательным переключением.
5. Обновите обработку ошибок
Устаревшие сервисы передавали ошибки через callback-функции. Замены на REST API возвращают HTTP-коды статуса. Логика обработки ошибок должна быть обновлена соответствующим образом.
Пошаговое руководство по замене API
DirectionsService на MapAtlas Directions API
До (Google, устаревший):
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);
}
}
);
После (MapAtlas Directions API):
const response = await fetch(
"https://api.mapatlas.com/v1/directions?" +
new URLSearchParams({
origin: "52.52,13.405",
destination: "48.8566,2.3522",
waypoints: "50.9375,6.9603",
mode: "driving",
key: process.env.MAPATLAS_API_KEY!,
})
);
const data = await response.json();
if (data.status === "OK") {
const leg = data.routes[0].legs[0];
console.log("Distance:", leg.distance.text);
console.log("Duration:", leg.duration.text);
// Polyline for map rendering
const polyline = data.routes[0].overview_polyline;
}
Ключевые отличия:
- REST endpoint вместо класса JavaScript. Вызовы идут с бэкенда, а не из браузера.
- Упрощённая аутентификация. Один API-ключ в строке запроса или заголовке.
- Та же структура ответа. Routes, legs, distance, duration и polyline — всё присутствует.
DistanceMatrixService на MapAtlas Matrix API
До (Google, устаревший):
const service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [
{ lat: 52.52, lng: 13.405 },
{ lat: 48.1351, lng: 11.582 },
],
destinations: [
{ lat: 48.8566, lng: 2.3522 },
{ lat: 51.5074, lng: -0.1278 },
],
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);
});
});
}
}
);
После (MapAtlas Matrix API):
const response = await fetch("https://api.mapatlas.com/v1/matrix", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${process.env.MAPATLAS_API_KEY}`,
},
body: JSON.stringify({
origins: [
{ lat: 52.52, lng: 13.405 },
{ lat: 48.1351, lng: 11.582 },
],
destinations: [
{ lat: 48.8566, lng: 2.3522 },
{ lat: 51.5074, lng: -0.1278 },
],
mode: "driving",
}),
});
const data = await response.json();
data.rows.forEach((row: any, i: number) => {
row.elements.forEach((element: any, j: number) => {
console.log(`Origin ${i} -> Dest ${j}:`,
element.distance.text, element.duration.text);
});
});
Структура ответа практически идентична. Главное изменение — переход с callback-ориентированного браузерного API на promise-ориентированный серверный API.
Замена Heatmap Layer
Путь миграции для визуализации тепловых карт зависит от конкретных требований:
Вариант 1: MapLibre GL JS с heatmap layer (open source)
import maplibregl from "maplibre-gl";
const map = new maplibregl.Map({
container: "map",
style: "https://api.mapatlas.com/v1/styles/streets?key=YOUR_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,
},
});
});
Это обеспечивает полный контроль над рендерингом тепловой карты без зависимости от тайловых серверов Google.
Вариант 2: deck.gl HeatmapLayer (собственная рекомендация Google)
import { Deck } from "@deck.gl/core";
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,
});
Оба варианта работоспособны. MapLibre GL JS чисто интегрируется со стилями тайлов MapAtlas, тогда как deck.gl может накладываться поверх любой базовой карты.
Сравнение стоимости: Google Routes API и MapAtlas
Переход на собственный Routes API Google — это не только изменение кода. Он влечёт за собой новое ценообразование:
| Сервис | Google (legacy, за 1 000) | Google Routes API (за 1 000) | MapAtlas (за 1 000) |
|---|---|---|---|
| Directions (базовый) | $5,00 | $5,00 | $1,50 |
| Directions (расширенный, waypoints/пробки) | $10,00 | $10,00 | $2,50 |
| Distance Matrix (за элемент) | $5,00 | $5,00 | $1,00 |
| Distance Matrix (расширенный) | $10,00 | $10,00 | $2,00 |
| Geocoding | $5,00 | $5,00 | $1,50 |
При 100 000 запросов маршрутизации в месяц:
- Google Routes API: около $500-$1 000 (в зависимости от используемых функций)
- MapAtlas Directions API: около $150-$250
Экономия быстро накапливается для приложений, сочетающих маршрутизацию с геокодированием и расчётом расстояний. Логистическая платформа, обрабатывающая 500 000 элементов матрицы в месяц, заплатит у Google порядка $2 500 против $500 в MapAtlas.
Подробная информация о ценах приведена в разделе ценообразование MapAtlas.
Примеры миграции кода: полное сравнение до и после
Ниже приведён полный пример миграции для React-компонента, отображающего маршруты на карте.
До: Google Maps DirectionsService в React
import { useEffect, useRef } from "react";
function DirectionsMap({ origin, destination }: {
origin: google.maps.LatLngLiteral;
destination: google.maps.LatLngLiteral;
}) {
const mapRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const map = new google.maps.Map(mapRef.current!, {
center: origin,
zoom: 7,
});
const directionsRenderer = new google.maps.DirectionsRenderer();
directionsRenderer.setMap(map);
const directionsService = new google.maps.DirectionsService();
directionsService.route(
{
origin,
destination,
travelMode: google.maps.TravelMode.DRIVING,
},
(result, status) => {
if (status === "OK" && result) {
directionsRenderer.setDirections(result);
}
}
);
}, [origin, destination]);
return <div ref={mapRef} style={{ width: "100%", height: "400px" }} />;
}
После: MapAtlas Directions API с 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://api.mapatlas.com/v1/styles/streets?key=YOUR_KEY",
center: [origin.lng, origin.lat],
zoom: 7,
});
map.on("load", async () => {
// Fetch directions from your backend (or directly if CORS allows)
const res = await fetch(
`/api/directions?` +
new URLSearchParams({
origin: `${origin.lat},${origin.lng}`,
destination: `${destination.lat},${destination.lng}`,
mode: "driving",
})
);
const data = await res.json();
if (data.routes?.[0]) {
const coordinates = data.routes[0].geometry.coordinates;
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,
},
});
// Fit map to route bounds
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" }} />;
}
Backend API Route (Next.js)
// app/api/directions/route.ts
import { NextRequest, NextResponse } from "next/server";
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const origin = searchParams.get("origin");
const destination = searchParams.get("destination");
const mode = searchParams.get("mode") || "driving";
const response = await fetch(
`https://api.mapatlas.com/v1/directions?` +
new URLSearchParams({
origin: origin!,
destination: destination!,
mode,
key: process.env.MAPATLAS_API_KEY!,
})
);
const data = await response.json();
return NextResponse.json(data);
}
Данный паттерн сохраняет API-ключ на сервере и передаёт клиенту только геометрию маршрута.
Тестирование миграции до наступления крайнего срока
Шаг 1: Запуск обоих API параллельно
За две недели до переключения вызывайте как старый сервис Google, так и новую замену для каждого запроса. Логируйте оба ответа и сравнивайте их:
async function getDirectionsWithComparison(
origin: string,
destination: string
) {
const [googleResult, mapatResult] = await Promise.all([
fetchGoogleDirections(origin, destination),
fetchMapAtlasDirections(origin, destination),
]);
// Compare key metrics
const distanceDelta = Math.abs(
googleResult.distance - mapatResult.distance
);
const durationDelta = Math.abs(
googleResult.duration - mapatResult.duration
);
console.log({
route: `${origin} -> ${destination}`,
googleDistance: googleResult.distance,
mapatDistance: mapatResult.distance,
distanceDeltaPercent: ((distanceDelta / googleResult.distance) * 100).toFixed(1),
googleDuration: googleResult.duration,
mapatDuration: mapatResult.duration,
durationDeltaPercent: ((durationDelta / googleResult.duration) * 100).toFixed(1),
});
// Use MapAtlas result in production, Google as validation
return mapatResult;
}
Шаг 2: Настройка feature flags
Управляйте выбором API с помощью feature flag. Это позволяет мгновенно откатиться при возникновении проблем:
const useMapAtlasDirections = process.env.FEATURE_MAPATLAS_DIRECTIONS === "true";
const directions = useMapAtlasDirections
? await fetchMapAtlasDirections(origin, destination)
: await fetchGoogleDirections(origin, destination);
Шаг 3: Мониторинг показателей ошибок
После переключения отслеживайте:
- Частоту ошибок HTTP 4xx/5xx нового API
- Рост задержки (новый провайдер может иметь другое время ответа)
- Отсутствующие поля в ответах, от которых зависит пользовательский интерфейс
- Точность маршрутов для граничных случаев (паромные маршруты, платные дороги, ограниченные зоны)
Шаг 4: Нагрузочное тестирование перед запуском
Если приложение обрабатывает пиковые нагрузки, как логистическая платформа в утренний период отправки, необходимо провести нагрузочное тестирование нового API при двукратном пиковом объёме. MapAtlas предоставляет среду sandbox для нагрузочного тестирования без биллинга в боевом режиме.
Хронология: что делать на этой неделе
Если миграция ещё не начата, следует придерживаться следующего порядка приоритетов:
- Эта неделя: Аудит кодовой базы. Выявите каждое обращение к четырём устаревшим сервисам.
- Неделя 2: Зарегистрируйтесь в MapAtlas и получите API-ключи. Бесплатный уровень включает 10 000 запросов для тестирования.
- Неделя 3: Реализуйте замену для наиболее критичного сервиса, как правило DirectionsService.
- Неделя 4: Перенесите оставшиеся сервисы и проведите параллельное тестирование.
- До майского дедлайна: Переключитесь окончательно, устраните зависимости от Google API, обновите биллинг.
Миграция не является опциональной. После мая 2026 года устаревшие классы будут удалены из Maps JavaScript API, и любой код, обращающийся к ним, будет генерировать ошибки во время выполнения. Начните сейчас — и у вас будет время на полноценное тестирование. Дотяните до последней недели — и придётся вносить исправления в продакшн под давлением.
По вопросам сопровождения миграции MapAtlas предоставляет прямую техническую поддержку разработчикам. Обратитесь через страницу контактов или начните изучение с документации API, чтобы оценить замещающие API применительно к вашим требованиям.
Часто задаваемые вопросы
Когда именно вступают в силу устаревания API Google Maps?
Heatmap Layer и Drawing Library были объявлены устаревшими в августе и мае 2025 года соответственно, с удалением запланированным на май 2026 года. DirectionsService и DistanceMatrixService признаны устаревшими 25 февраля 2026 года, также с целевой датой удаления в мае 2026 года. После удаления вызовы API к этим сервисам будут возвращать ошибки.
Будет ли работать мой существующий API-ключ Google Maps JavaScript после мая 2026 года?
API-ключ продолжит работать для неустаревших сервисов. Однако любой код, вызывающий DirectionsService, DistanceMatrixService, Heatmap Layer или Drawing Library через Maps JavaScript API, перестанет функционировать. Необходимо перенести эти конкретные вызовы на замещающие API до наступления крайнего срока.
Какова наиболее дешёвая альтернатива Google Maps Directions API?
MapAtlas предлагает Directions API примерно на 70% дешевле, чем эквивалент Google. Бесплатный уровень включает 10 000 запросов в месяц, чего достаточно для разработки и тестирования миграции. Среди других альтернатив — Mapbox, HERE и OpenRouteService, однако MapAtlas предоставляет формат запросов/ответов, наиболее близкий к Google, что снижает трудозатраты на миграцию.
Можно ли мигрировать поэтапно или нужно переключить всё сразу?
Поэтапная миграция возможна. Каждый устаревший сервис независим, поэтому можно сначала заменить DirectionsService, затем DistanceMatrixService, после чего перейти к библиотекам визуализации. Именно такой подход рекомендуется, поскольку позволяет тестировать каждую замену в изоляции до перехода к следующей.
Поддерживает ли MapAtlas те же waypoints и режимы передвижения, что и Google DirectionsService?
Да. MapAtlas Directions API поддерживает режимы driving, walking и cycling, а также промежуточные waypoints. Формат запроса несколько отличается (RESTful endpoint вместо класса JavaScript), однако основная функциональность, многоточечная маршрутизация с выбором режима передвижения, является эквивалентной.

