Geofencing Service — Detailed#
flowchart TB
subgraph Sources
DEV([Devices / phones])
VEH[Vehicles]
DRONE[Drones / IoT]
end
subgraph Ingest
LB
ING([Location ingest])
BATCH[Batch + dedup]
end
subgraph Geofences[Fence registry]
REG[Fence Registry]
REGDB[(Fences DB<br/>polygon / circle / multipoly)]
IDX[(Spatial index<br/>R-tree / S2 / H3)]
SUB[Subscriptions per fence]
end
subgraph Eval[Evaluation Engine]
MATCH[Point-in-polygon test]
HYS[Hysteresis<br/>avoid bounce]
STATE([(Per-device per-fence state)])
DEBOUNCE[Debounce / dwell]
EVTGEN[Enter / Exit / Dwell event]
end
subgraph Delivery
BUS[[Kafka events]]
WH[Webhook delivery]
PUSH((APNS / FCM))
INAPP[In-app realtime]
DLQ[[(DLQ)]]
end
subgraph Ops
METR[Metrics]
AUDIT[Audit]
ML[Pattern detection]
end
Sources --> LB --> ING --> BATCH
BATCH --> MATCH --> Eval
Eval --> STATE
Eval --> EVTGEN --> BUS
Geofences --> MATCH
IDX --- MATCH
BUS --> WH
BUS --> PUSH
BUS --> INAPP
WH --> DLQ
classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
class DEV client;
class VEH,DRONE,BATCH,REG,SUB,MATCH,HYS,DEBOUNCE,EVTGEN,WH,INAPP,AUDIT,ML service;
class REGDB,IDX,STATE,DLQ datastore;
class BUS queue;
class ING compute;
class PUSH external;
class METR obs;
Index for point-in-polygon#
- R-tree on bounding boxes is the classic.
- Modern: S2 / H3 cell coverings; a fence covers a set of cells.
- Lookup: cell of the device → fences whose covering contains it → exact PIP test.
Hysteresis#
- Avoid event spam when device sits on the border.
- Require N consecutive INSIDE updates to fire ENTER; same for EXIT.
- Dwell event after T minutes inside.
Delivery#
- At-least-once webhooks with retry + DLQ.
- Idempotency by
(device, fence, event_id).
Glossary & fundamentals#
Concepts referenced in this design. Each row links to its canonical page; the tag column shows whether it is a high-level (HLD) or low-level (LLD) concept.
| Tag | Concept | What it is | Page |
|---|---|---|---|
HLD |
Pub/Sub & message brokers | topics, consumer groups, delivery semantics | pub-sub-pattern |
HLD |
Idempotency & retries | safe re-execution, backoff + jitter | idempotency-retries |
HLD |
Observability | metrics, logs, traces, SLOs | observability |
HLD |
Geo indexing | Geohash, Quadtree, S2, H3, R-tree | geo-indexing |