GeoIP & GeoSite Database Updates: Root Cause of Routing Drift

How GeoIP and GeoSite databases power rule matching, two update methods (manual swap and auto-update), plus symptoms of stale data and how to verify fixes.

Routing rules in Clash and the mihomo core don't rely solely on hand-written domains or IP ranges. Many common rules actually reference two offline databases: GeoIP and GeoSite. These bundle massive sets of IP ranges and domain names into categories, so a rule file only needs a single line like GEOIP,CN or a reference to a rule set to cover thousands of real-world addresses. This keeps configs concise, but it also hides an easily overlooked risk — the databases themselves have a shelf life, and stale versions can quietly make otherwise correct rules misfire.

What GeoIP and GeoSite Actually Store

These two databases solve the same problem from two different angles: one classifies by IP, the other by domain. Understanding the difference is the starting point for diagnosing routing anomalies.

DimensionGeoIPGeoSite
Content storedMapping of IP ranges to country/region codesMapping of domains to service categories
Common filesCountry.mmdb / geoip.metadbgeosite.dat / GeoSite.dat
Typical rule syntaxGEOIP,CN,DIRECTRULE-SET,geosite-google,PROXY
Common update triggersIP range reallocation, cloud provider data center migrationsNew domains going live, CDN domain changes

The mihomo core loads both databases into memory at startup, and every subsequent connection is matched by looking up a table — which country an IP belongs to, or which category a domain falls under. Anything missing from the database simply can't hit the corresponding rule and falls through to later rules, usually landing on the catch-all MATCH policy at the bottom of the rule list — which often doesn't match the intended exit.

Symptoms of an Outdated Database

Stale databases don't throw errors or prompt you to update — it's a silent drift that can only be inferred from abnormal routing results. Here are the most common patterns:

  • A newly launched service gets misclassified as local: Cloud providers sometimes assign newly issued IP ranges to a specific region. If GeoIP hasn't caught up with that assignment, connections to the new service may be wrongly matched by a GEOIP,CN rule as a local IP, sent through direct connection, and time out or fail.
  • A correctly written rule set never matches: If a GeoSite rule set (say, for streaming or social apps) recently added new domains that the database hasn't picked up yet, those new domains bypass the rule set entirely and fall to the default policy — showing up as "the same app, some features proxy, others go direct."
  • Local sites occasionally route through the proxy: Conversely, if an IP range is reclaimed by a cloud provider or transferred to an entity outside mainland China, an outdated database that still marks it as local can push traffic that should go direct out through the proxy instead, causing a noticeable slowdown.
  • Latency tests look fine but real access fails: Node latency tests hit a fixed test URL and don't go through full domain/IP routing logic, so problems caused by stale databases are often invisible during speed tests and only surface when accessing the real business domain.

If you haven't changed any rules or subscriptions recently but some sites suddenly route incorrectly, suspect the GeoIP/GeoSite database version first rather than rushing to rewrite rules — in most cases the rules themselves are fine.

Manually Replacing the Database Files

Manual replacement is the most direct and controllable option — good for confirming a diagnosis or for cases where you don't fully trust the auto-update mechanism. There are only three core steps: locate the core's data directory, download the latest database files, and restart the core to reload them.

  1. Find the data directory: By default, the mihomo core looks for Country.mmdb and geosite.dat (or the equivalent .metadb format) in its working directory. On desktop this is usually alongside the config directory; on the iOS client, both items are typically listed separately in the app's rules/data management screen, so there's no need to locate a filesystem path manually.
  2. Get the latest database: Databases are maintained and released through the rule set repositories of mihomo-related open-source projects, typically on a cadence of a few weeks, with targeted patch releases when a large IP reallocation or a popular domain migration happens.
  3. Replace and restart: After overwriting the old files with new ones, you must fully restart the core (reloading the config alone usually doesn't reload the databases), otherwise the in-memory mapping table still reflects the old version and the swap has no effect.

If the client offers a graphical "Update GeoIP/GeoSite" button, use that instead — it handles file verification and the restart flow automatically, and is far less error-prone than manually touching the filesystem.

Two Ways to Enable Auto-Update in Config

Manual replacement is ultimately something you only do after a problem shows up. It's better to enable auto-update in the config and let the core check on a schedule. mihomo provides two independently configurable layers.

Layer 1: Core-Level GeoIP/GeoSite Auto-Update

This layer controls the built-in geo-databases themselves, set at the top level of the config file:

geodata-mode: true
geo-auto-update: true
geo-update-interval: 24
geox-url:
  geoip: "https://example-mirror.invalid/country.mmdb"
  geosite: "https://example-mirror.invalid/geosite.dat"

geo-update-interval is in hours and determines how often the core checks the remote source for a new version; geox-url can point to a self-hosted or third-party mirror to speed up downloads or work around unstable access. Once enabled, no manual intervention is needed — the core updates silently in the background.

Layer 2: Independent Updates for Rule Providers

If your routing rules use external rule sets rather than the core's built-in GeoSite categories, the update interval needs to be declared separately in each rule-provider:

rule-providers:
  reject-list:
    type: http
    behavior: domain
    url: "https://example-mirror.invalid/reject.txt"
    path: ./rules/reject.yaml
    interval: 86400

interval is in seconds, so 86400 means once a day. Rule providers and the core's built-in GeoIP/GeoSite are two separate update channels — enabling one doesn't cover the other, which is a common reason behind "I updated the database but the rules still don't match."

Auto-update relies on the client staying active in the background or waking on schedule. For devices where the client is rarely launched, it's worth periodically triggering a manual update as well.

Verifying the Update Actually Took Effect

After replacing files or changing the config, don't just assume it worked — run through a repeatable verification process.

  1. Check the startup log: When the core restarts, it logs database load info, including file paths and record counts. If you see a download failure or a checksum error in the log, the update didn't actually take effect and the rules are still running on old data.
  2. Test against a known edge case: Pick a domain or IP that recently changed ownership, and test its routing result before and after the update. If the exit policy changes as expected, the new database has been loaded and is being used for matching.
  3. Compare rule set entry counts: Some clients' rule management screens show the current number of domains or IPs in each rule set. A visible change in that count before and after is direct evidence the database was actually refreshed.
  4. Clear the connection cache before retesting: Some cores briefly cache the result of an established connection. Disconnect and reconnect, or restart the client, before verifying, to avoid a stale cached result skewing your test.

Verification may feel like extra steps, but it saves far more time than assuming "it's done once updated" — database-related routing issues tend to be subtle and delayed, and building this habit early can save a lot of log-digging later on.

Setting a Sustainable Update Cadence

For most use cases, enabling core-level auto-update with a 12–24 hour check interval is plenty — there's no need to chase minute-level real-time syncing, and the upstream release cadence for GeoIP and GeoSite doesn't support that frequency anyway. If routing issues keep showing up on the same category of service, it's more worthwhile to check whether the rule set source for that category is still actively maintained, rather than endlessly shortening the update interval. Database updates are just one piece of routing accuracy — pairing them with regular log checks and attention to rule match results is what keeps occasional drift to a minimum.

Download the Clash Client for iOS

After getting the official client, open the rules and data management screen to check the current GeoIP/GeoSite version and trigger an update, then follow the setup guide for first-time configuration.

Download client