Skip to content

How We Built Geofencing Into a Multi-Service AI Platform

How We Built Geofencing Into a Multi-Service AI Platform

Three access tiers, two services, one shared geo pipeline: no room for error.

Visualisation of Geofencing Regions


Why Bother?

The board agreed on a clear strategic direction: Mirror Ai needed to operate across multiple jurisdictions, each with its own regulatory and compliance requirements. The fragmented nature of the space meant that focusing on the rules of one region was starting to restrict our ability to offer value in others.


We needed a way to tailor what users could see and do based on where they were. Not just a simple block-everything-except approach, but a graduated system that could handle the three tiers our compliance work had identified:

  • Sanctioned jurisdictions — cannot access the website at all
  • Regulated jurisdictions — basic access, with certain features restricted
  • Open access jurisdictions — full access to all services

This is the story of how we built that system.


The Technical Challenge

Our platform is modular by design. The Mirror Ai Architecture Article covered the four layers: user interfaces, agent orchestration, data integration, and storage. Modularity gives us flexibility, but it also means geofencing is not a single switch you flip. It is a capability that needs to work across every service, every API endpoint, and every page.


The architecture article covered the big picture. This article is about what happens when you need to implement a cross-cutting concern like geofencing across a modular stack.


We have two main services that urgently needed geo enforcement: the UI service and the dashboard service. They share a database but run independently. Any solution we built had to work in both without creating a dependency between them. Success with these services would offer an extensible pattern to apply more broadly across our tech stack.


The Three-Layer Pipeline

Every request passes through three stages before the user sees a response.

Layer 1: Geo Enrichment

The first thing that happens on every request is an IP lookup. We take the client IP, hash it using HMAC-SHA-256 with a shared secret, and look up the using a solution baked into the Docker images.


The hash is deterministic. The same IP produces the same hash in both services, which lets us join analytics across services without ever storing raw IP addresses, which is critical because privacy concerns are important to us.


The result is stored in a PostgreSQL table with SCD2 versioning, so we have a full audit history of when an IP was first seen and what country it resolved to.


This runs as a before_request hook on every request. It never raises an error. If the lookup fails for any reason, the request still proceeds.

Layer 2: Geo Policy Evaluation

Once we know the country, we look up its access level in a policy table. The table maps country codes to one of our geofencing policy states. We took the important architectural decision to make this a pure geographic lookup. There is no product-tier logic mixed in.


This might seem trivial at first, but it's really important because if we made the wrong architectural decision here, we would incur immediate technical debt and unnecessary complexity. Separating geofencing from product definition allows us to manage each policy with the appropriate level of freedom and detail.

Layer 3: Enforcement

The enforcement layer is where the three tiers actually take effect:

  • Denied Regions: The user sees a full-page block with a contextual message. No access to anything.
  • Restricted Regions: The user sees a sticky amber banner and certain features are greyed out with lock badges. For the dashboard, a JSON policy blob is injected into the SPA shell so the frontend knows which sections to gate.
  • Unrestricted Regions: Full access to everything.

Tier Access Level UX
Sanctioned Denied Full-page block, no access
Regulated Restricted Amber banner, greyed-out features
Open Unrestricted Full access

The Section Restrictions

Not all features are created equal. Some sections like general market data are relatively low-risk and can be shown to all users. Others like DeFi analytics and project security tools carry more potential regulatory risk and we need to be able to manage access.


In the first deployed iteration, I elected to implement the simplest possible architecture, to ensure that we could rapidly test and deploy this important capability. Any issues and unknowns can be explored quickly and the current components provide the foundation for maturing and developing the architecture to ensure that it will be fit for purpose.


What We Learned

Independent enrichment was the right call. The dashboard does not depend on the UI service having already enriched the request. Therefore, direct Dashboard-only traffic is enriched independently, eliminating unnecessary cross-service dependency in exchange for a small amount of technical duplication.


Geo is not product tier. One of the early proposals mixed geographic restrictions with product-tier access control. Upon review, I decided that this was a poor architectural choice, and we separated them during implementation, and that was the right decision. The two concerns have different rules, different audiences, and different change frequencies.


SCD2 versioning is worth the complexity. Knowing when a country's status changed and when an IP was first seen has been valuable for both compliance audits and debugging.


The frontend UX matters more than expected. Users in restricted regions need clear visual signals, such as sticky banners, lock badges, greyed-out cards. Without these, they end up confused about why certain features are missing. This impacts on their perception about our product offering and whether and, if not properly communicated, would cause them to doubt whether they are getting what they paid for!


The Audit Trail

Every geo lookup is logged. Every policy decision is recorded. The analytics tables tie each event back to the geographic context of the request. This lets us see traffic patterns by country, which feeds into both compliance reporting and product development decisions, making Mirror Ai operations more effective and efficient.


The TL;DR

Geofencing in a multi-service platform is not a single switch. It is a pipeline: enrich the request, evaluate the policy, enforce the decision. Three layers, each with a clear job, no cross-service dependencies, and a full audit trail.


The architecture gave us the flexibility to build this the right way:
The regulatory landscape gave us the motivation.
The implementation gave us a system that can grow with both.


References

  • Mirror Ai Stack Architecture: https://mirror.glasslane.io/blog/the-mirror-ai-stack-high-level-architecture-1
  • SCD2 (Slowly Changing Dimensions): https://en.wikipedia.org/wiki/Slowly_changing_dimension
Back to all articles
Demo Mode

Hi! I'm your AI assistant 🤖

I can help you with blockchain research, whitepaper analysis, and crypto market insights. Try asking me something!