NHT

Migrating from Google Maps API to a Vietnam Map API: Cost & Code

Compare Google Maps Platform pricing and Vietnam limitations, then migrate geocoding, reverse geocoding, and address autocomplete to GoGoDuk with real code.

Nguyen Hoang TuanNguyen Hoang Tuan12 Jun 20269 min read

Most Vietnamese products—delivery apps, e-commerce checkouts, logistics dashboards, CRMs—start on Google Maps Platform because it is the default choice. Over time, two walls tend to appear: cost that scales linearly with request volume, and address data that is not tuned for Vietnamese patterns such as diacritics, abbreviations, and the province/district/ward hierarchy.

This post compares the pricing and data-fit realities, then shows concrete before/after code to migrate the three most common features—address autocomplete, geocoding, and reverse geocoding—to GoGoDuk, a Vietnam-focused map API for developers. The goal is a low-risk, incremental migration rather than a big-bang rewrite.


Why Teams Reconsider Google Maps for Vietnam Products

Google Maps is an excellent global platform. But for products that operate exclusively in Vietnam, a focused API can be a better fit across three dimensions:

  • Cost: Geocoding, Places, and Autocomplete are billed by usage. As traffic grows, the per-request model compounds—and autocomplete in particular can surprise teams who do not manage session billing carefully.
  • Data fit: Vietnamese addresses involve diacritics, heavy abbreviation, renamed or merged administrative units, and users typing partial text. Global geocoders often return inconsistent province/district/ward context.
  • Integration weight: Pulling in a full global map SDK to power a single checkout field or an internal logistics tool is more dependency than the workflow needs.

If your location features are Vietnam-only, a Vietnam-first API narrows the problem. For a deeper look at that positioning, see our intro to GoGoDuk: Vietnam Map APIs Built for Developers.


Google Maps Platform Pricing Realities

The relevant Google Maps Platform APIs are billed by usage, and the model differs per feature. The table below summarizes the structure rather than exact figures, since pricing and credit policies change over time—always verify against the current Google Maps Platform pricing page.

| Feature | Google billing model | Notes | | --- | --- | --- | | Geocoding | Per 1,000 requests | Address → coordinates; cost grows linearly with volume | | Reverse Geocoding | Per 1,000 requests | Coordinates → address; same per-request scaling | | Places Autocomplete | Session-based | Billed per session; skipping session tokens can multiply cost | | Place Details | Per request | Often paired with autocomplete to resolve a selected prediction |

The autocomplete row is where teams most often get surprised. Google's autocomplete is designed to be billed per session—a sequence of keystroke requests plus the final Place Details call grouped under one session token. If you forget to attach session tokens, each keystroke can be billed independently, and a typeahead box that fires on every character becomes far more expensive than expected.


Mapping Google Maps Features to GoGoDuk

Before touching code, it helps to map each Google feature to its GoGoDuk equivalent so you know exactly what replaces what.

| Google Maps API | GoGoDuk equivalent | Endpoint | | --- | --- | --- | | Places Autocomplete | Address suggest | GET /v1/suggest?input=... | | Place Details | Place lookup | GET /v1/place/{placeId} | | Geocoding | Geocoding | GET /v1/geocode?address=... | | Reverse Geocoding | Reverse geocoding | GET /v1/reverse?lat=...&lng=... | | Geometry / boundaries | Administrative boundaries | Province / district / ward data |

Two practical differences to note. First, authentication: Google passes an API key as a key= query parameter, while GoGoDuk uses an X-API-Key request header—keep that key server-side. Second, evaluation: GoGoDuk offers a free tier of 100 requests per day with no credit card, which is enough to validate result quality against your real Vietnamese addresses before committing.


Migrating Address Autocomplete

Autocomplete is usually the highest-volume and highest-cost feature, so migrate it first. Here is the typical Google Places Autocomplete flow with a session token:

// Before — Google Places Autocomplete (session-based billing)
const sessionToken = new google.maps.places.AutocompleteSessionToken();
const service = new google.maps.places.AutocompleteService();

function suggestAddress(input: string) {
  return new Promise((resolve, reject) => {
    service.getPlacePredictions(
      {
        input,
        sessionToken,
        componentRestrictions: { country: "vn" },
      },
      (predictions, status) => {
        if (status !== google.maps.places.PlacesServiceStatus.OK) {
          return reject(new Error(status));
        }
        resolve(predictions ?? []);
      },
    );
  });
}

The GoGoDuk equivalent is a plain REST call—no SDK, no session token management, and trivial to debounce or cache:

// After — GoGoDuk address suggest (plain REST, server-side)
async function suggestAddress(input: string) {
  if (input.trim().length < 3) return [];

  const response = await fetch(
    `https://api.gogoduk.com/v1/suggest?input=${encodeURIComponent(input)}`,
    {
      headers: { "X-API-Key": process.env.GOGODUK_API_KEY! },
    },
  );

  if (!response.ok) {
    throw new Error("Unable to load address suggestions");
  }

  return response.json();
}

The integration pattern stays the same: debounce user input, request suggestions, let the user pick a result, then store the stable identifier returned by the API. For the full UX side—debounce timing, keyboard navigation, and conversion impact—see our guide on Optimizing Checkout Conversion with Vietnam Address Autocomplete.


Migrating Geocoding

Geocoding turns an address string into coordinates. The Google REST call looks like this:

// Before — Google Geocoding API
async function geocode(address: string) {
  const url = `https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent(
    address,
  )}&region=vn&key=${process.env.GOOGLE_MAPS_KEY}`;

  const res = await fetch(url);
  const data = await res.json();
  const top = data.results?.[0];

  return {
    lat: top?.geometry.location.lat,
    lng: top?.geometry.location.lng,
    placeId: top?.place_id,
  };
}

With GoGoDuk, the request moves to the /v1 base with the X-API-Key header, and you parse the response into the same shape:

// After — GoGoDuk Geocoding
async function geocode(address: string) {
  const res = await fetch(
    `https://api.gogoduk.com/v1/geocode?address=${encodeURIComponent(address)}`,
    { headers: { "X-API-Key": process.env.GOGODUK_API_KEY! } },
  );

  if (!res.ok) throw new Error("Geocoding failed");
  const data = await res.json();
  const top = data.results?.[0];

  return {
    lat: top?.lat,
    lng: top?.lng,
    placeId: top?.placeId,
  };
}

A useful cost-saving habit: store the stable placeId (and the resolved coordinates) the first time you geocode an address, then reuse it instead of re-geocoding the same input on every request. This keeps your usage flat for repeat addresses regardless of provider.


Migrating Reverse Geocoding

Reverse geocoding turns coordinates into a human-readable address. For Vietnam, the important detail is administrative context—province, district, and ward—which a global geocoder returns inconsistently. The Google call:

// Before — Google Reverse Geocoding
async function reverseGeocode(lat: number, lng: number) {
  const url = `https://maps.googleapis.com/maps/api/geocode/json?latlng=${lat},${lng}&key=${process.env.GOOGLE_MAPS_KEY}`;
  const res = await fetch(url);
  const data = await res.json();
  return data.results?.[0]?.formatted_address;
}

GoGoDuk returns the Vietnamese administrative hierarchy natively, so you get province/district/ward fields without parsing them out of a flat formatted string:

// After — GoGoDuk Reverse Geocoding
async function reverseGeocode(lat: number, lng: number) {
  const res = await fetch(
    `https://api.gogoduk.com/v1/reverse?lat=${lat}&lng=${lng}`,
    { headers: { "X-API-Key": process.env.GOGODUK_API_KEY! } },
  );

  if (!res.ok) throw new Error("Reverse geocoding failed");
  const data = await res.json();

  return {
    address: data.address,
    province: data.province,
    district: data.district,
    ward: data.ward,
  };
}

Native province/district/ward fields are particularly valuable for logistics and delivery zones. If you need to enrich addresses or assign shipping regions from coordinates, see Working with Vietnam Administrative Boundaries.


A Practical Migration Checklist

You do not need a risky big-bang switch. Migrate incrementally behind a thin adapter so the provider is swappable:

  1. Inventory current usage. List every Google Maps API call in your codebase and estimate monthly request volume per feature.
  2. Get a free-tier key. Sign up for GoGoDuk (100 requests/day, no credit card) and test /v1/suggest against your real Vietnamese inputs.
  3. Wrap calls behind an adapter. Define a small LocationProvider interface (suggest, geocode, reverse) so swapping providers is a one-file change.
  4. Migrate autocomplete first. It is usually the biggest cost line, and the suggest endpoint is the simplest swap.
  5. Then geocoding and reverse geocoding. Move them once autocomplete is verified.
  6. Cache stable place IDs. Avoid re-resolving the same addresses on every request.
  7. Run in shadow mode. Call both providers in parallel for a short period and compare result quality on real traffic before cutting over.
  8. Cut over and monitor. Switch the adapter to GoGoDuk and watch latency, error rate, and result quality.

If you prefer not to write raw fetch calls, GoGoDuk also ships a lightweight TypeScript SDK at gogoduk.com/docs/sdks/typescript.


Summary and Key Takeaways

Migrating Vietnam map features off Google Maps comes down to three points:

  1. The cost models differ structurally. Google bills per request and per autocomplete session; understand session-token billing before assuming your costs.
  2. The core features map cleanly. Autocomplete, geocoding, and reverse geocoding each have a direct GoGoDuk REST equivalent using the X-API-Key header.
  3. Migrate behind an adapter, autocomplete first. A swappable LocationProvider interface plus shadow-mode comparison makes the switch low-risk.

In practice, migrating is mostly a matter of swapping REST calls behind a small abstraction—and GoGoDuk's free tier (100 requests/day, no credit card) lets you validate result quality on real Vietnamese addresses before committing. For the autocomplete UX details, see our guide on Vietnam Address Autocomplete for Checkout UX, and explore the endpoints and TypeScript SDK in the GoGoDuk docs.

Facing performance issues or scaling challenges?

I specialize in building low-latency map infrastructure, real-time streaming pipelines (Kafka, ClickHouse), and highly optimized backend systems. Let's work together to scale your product.

Let's Work Together

Written by

Nguyen Hoang Tuan

Nguyen Hoang Tuan

Full-stack developer focused on practical backend architecture, web performance, and production delivery.

Related Articles