Technical Architecture

Attendance that works where the network doesn't.

TraceOn tracks attendance and field movement for people who don't sit at a desk — sales teams, service engineers, distribution staff, site supervisors. We built it around a single assumption: the phone will lose signal, the battery will be low, and the data still has to be right.

Live session TRACKING
my_location
TraceOn is tracking your shift
Foreground service · you can stop this any time
A day's movement trail A path of GPS points from check-in to check-out. A shaded stretch in the middle marks the period with no connectivity, where points were captured locally and synced later. OFFLINE CHECK-IN CHECK-OUT
The problem, stated honestly

Field attendance isn't an app problem. It's a systems problem.

Attendance software for office staff is a solved problem. Point a laptop at a login page and you're done. Field attendance is different — four constraints shaped every decision we made.

signal_disconnected
01

The network is not a given.

A field executive in a basement warehouse, a rural highway, or a factory floor has no usable connectivity for hours at a time. Any design that assumes an online API call at the moment of check-in loses data.

battery_alert
02

The OS is actively working against you.

Android and iOS aggressively suspend background apps to protect battery. An app that naively polls GPS every minute either gets killed or drains the phone by lunchtime — and a drained phone is an untracked employee.

shield_with_heart
03

Some people will try to game it.

Mock-location apps are one Play Store search away. Attendance data that can be trivially faked is worse than no data, because it looks authoritative.

account_tree
04

Real organisations have shape.

Companies aren't flat lists of employees. They have branches, designations, reporting lines, and managers who must see their own team and nothing else. Multiple companies share the same infrastructure and must never share a single row of data.

Everything below is how we answered these four.

The system at a glance

Three surfaces over one core.

Every byte the mobile app produces and every screen the portal renders goes through one API, one permission model, one database. There is no second source of truth to reconcile.

View text / ASCII version of this diagram
   [ Mobile App ]                          [ Admin Portal ]
    Flutter/Android                          React/TypeScript
    capture · queue · sync                   monitor · report · configure
          |                                          |
          |  HTTPS + JWT (batched, resumable)        |  HTTPS + JWT
          +------------------+-----------------------+
                             |
                    [ TraceOn Core — NestJS ]
                    auth · tenancy · business rules
                             |
                    [ PostgreSQL via Prisma ]
                             |
              [ Background services: watchdog · auto-close ]
                             |
                 push / email  ·  customer HR & SSO

"The network is an optimisation, never a dependency."

01 · Capture first, sync later

Never lose a day to a dead zone.

The problem. If a check-in only exists after a successful HTTP call, then a dead zone means a lost day — and a manual correction later, which is exactly the manual process the product was meant to remove.

How we solved it. The mobile app treats local storage as the system of record until the server confirms otherwise.

  • check_circleEvery GPS reading is written to a local breadcrumb store before any upload is attempted. The store is bounded and self-trimming, so a long offline stretch can't fill the device.
  • check_circleA full offline workday — check-in, the movement trail, check-out — is queued locally as a complete session, with client-generated identifiers on every record.
  • check_circleWhen connectivity returns, the app replays the queue in bulk to a dedicated sync endpoint.
  • check_circleBecause the server deduplicates on those client-generated IDs, the sync is idempotent. A half-completed upload, a dropped connection, or an aggressive retry produces exactly one record — never a duplicate, never a gap.
  • check_circleSync fires on the two events that actually matter: connectivity coming back, and the app returning to the foreground. No fixed polling, no wasted radio.
  • check_circleUploads are throttled and batched rather than sent per-point, so tracking costs the employee's data plan and battery very little.
Why it matters to you

Field staff in low-coverage areas produce the same quality of attendance record as staff sitting in your head office. Your operations team stops arbitrating "my phone had no signal" disputes, because the trail was captured whether or not the network was there.

The offline workday
login
Check-in
Written locally first, with a client-generated ID
Offline stretch · no network signal_disconnected

Breadcrumbs accumulate in the local store. Bounded, self-trimming, queued as one complete session.

wifi
Signal returns
Sync triggers on connectivity + foreground — not on a timer
arrow_drop_down
cloud_upload
One batched sync
Bulk replay to a dedicated endpoint · throttled
arrow_drop_down
fingerprint
Server deduplicates
Idempotent on client IDs — exactly one record, every time
A safety net, not a single mechanism
02 · Background tracking that survives the OS

Track continuously without becoming the app people uninstall.

The problem. Continuous GPS is the fastest way to drain a phone, and modern Android will kill an app that tries. Either failure mode ends the same way — the employee turns tracking off.

How we solved it. Hybrid tracking, plus a server that notices when a device goes quiet.

  • check_circleThe app runs a foreground service with a persistent notification — visible, honest, and the only pattern the OS reliably keeps alive. The employee always knows tracking is on.
  • check_circleLocation is driven primarily by a distance filter, with a timed fallback for when the OS stalls the location stream.
  • check_circleWake-lock handling and a guided battery-optimisation exemption flow stop the device from quietly suspending the service. Permissions are requested with an explicit rationale screen before the OS dialog.
  • check_circleTracking frequency is a per-company setting, not a hardcoded constant. A delivery fleet and a monthly-visit sales team get different profiles from the same product.
  • check_circleOn the server, a staleness watchdog sends a silent push notification that wakes the background service — recovering tracking automatically.
Why it matters to you

Coverage stays high without the battery complaints that kill adoption of tracking products. And when a device does go dark, your system knows and acts — rather than discovering the gap in a report a week later.

"A drained phone is an untracked employee."

03 · Location data you can defend

Record the doubt alongside the data.

The problem. Attendance data drives payroll, incentives and performance reviews. If it can be faked, every decision made from it is contestable.

How we solved it. We don't just capture where the phone says it is — we capture how much that claim can be trusted.

  • check_circleEvery location reading carries a mock-location flag. The OS tells us when a coordinate came from a spoofing app, and we persist that with the point rather than silently accepting it.
  • check_circleThe app performs an additional developer-mode check through a native platform channel, catching the common spoofing setup before it produces a record.
  • check_circleWhen tampering is detected, check-in and check-out are blocked and the reason is shown to the employee — a clear signal, not a silent failure.
  • check_circleThe trail is structurally auditable: every GPS point is bound to a specific attendance session and stamped with when it was recorded and whether it came from a deliberate action or automatic background tracking. Nothing floats free of its session.
  • check_circleSessions that were never closed are auto-closed by a scheduled job with a system-attributed reason, so a forgotten check-out can't inflate hours and can't be confused with a manual entry.
Why it matters to you

When an attendance record is challenged — by an employee, an auditor, or your own finance team — you can show the full trail, its origin, and its integrity flags. That's the difference between data and evidence.

One location record, as stored
session_idatt_9f3c…21b7
latitude17.4923
longitude78.3915
accuracy_m8.0
recorded_at2026-08-02 11:42:07
sourceBACKGROUND_TRACK
is_mockedfalse ✓

Nothing floats free of its session. The origin and the doubt travel with the point.

sourceCHECK_IN
is_mockedtrue ⚠
resultBLOCKED · reason shown

"Data becomes evidence when you can show where it came from."

Tenancy, and scope inside it
Company A
Company B

— no connection · not one shared row —

Director — Operations
Company A · root
Regional Manager
viewing the system
In scope
Area Manager
reports to Regional Manager
Field Executive
Field Executive
Regional Manager — West
peer subtree · out of scope

A recursive query walks the viewer's actual reporting subtree on every request. Promote someone, and the scope is correct on the next page load.

04 · Built for real organisational structure

The permission model follows the org chart, and the database enforces it.

The problem. Multi-tenant SaaS fails in two directions: leaking one customer's data into another's, and giving every manager inside a customer the same god-view of the whole company.

  • check_circleEvery record is keyed to a company. Employees, branches, roles, hierarchy levels, sessions and location history all carry the tenant key, and every query is scoped by it before it reaches the database. Employee codes are unique within a company, so customers keep their own conventions.
  • check_circleThe employee hierarchy is a genuine tree, not a role label. Employees report to employees.
  • check_circleA manager's scope is resolved with a recursive query that walks their actual reporting subtree — computed in the database on every request, so it stays correct the moment someone is promoted or moved.
  • check_circleLevels and designations are configurable per company, with ordering rules that reshape the chart safely. Promotions and role changes leave a history trail rather than overwriting the past.
  • check_circleAn admin can view the system as one of their managers for support. Impersonation is explicit, permission-checked, and written to the audit log every time — never a hidden back door.
  • check_circleAccess is enforced by layered guards on every route: a signed token establishes identity and role, role guards gate the endpoint, tenant checks gate the data. All three have to pass.
Why it matters to you

Your reporting structure is reflected in the software instead of being flattened by it — and your data isolation isn't a policy promise, it's how the queries are written.

The stack, and why

Chosen for the hard parts, not for the résumé.

Mobile app
Flutter (Dart), Android-first

One codebase, native-grade access to background services, foreground notifications and GPS.

Location & background
Native foreground service, platform channels, push wake-up

Battery and OS survival can't be solved at the framework layer alone.

Admin portal
React 18, TypeScript, Vite

Fast, type-safe, and quick to iterate as customers ask for new reports.

Portal UI
Tailwind + HeroUI, Leaflet, React Flow

A consistent design system, open mapping, and an interactive hierarchy view.

API
NestJS 11 on Node.js 22, TypeScript

Modules, DI and guards make a growing permission model tractable.

Data
PostgreSQL with Prisma ORM

Relational integrity for a hierarchy-heavy, audit-heavy domain.

Auth
In-house auth SDK, signed JWT + refresh

Shared across our products, so identity behaves identically everywhere.

Messaging
Push + templated transactional email

Silent wake-ups, alerts and onboarding mail through one service.

Delivery
Containerised, AWS, CI on merge

Reproducible builds; the same image runs in every environment.

Everything is TypeScript from the database schema to the browser. A change to the data model surfaces as a compile error in the portal, not as a bug in production.

How we build

Practices, not promises.

API-first.

Every endpoint is defined once and published as live OpenAPI documentation. The web portal and mobile app are both consumers of that contract — which is also why integrating a third system is a matter of days, not a project.

Nothing untrusted reaches the business logic.

Requests are validated against strict schemas at the edge; unknown fields are rejected rather than ignored, which closes off an entire class of mass-assignment bugs.

Every request is traceable.

Structured JSON logging with a correlation ID follows a single request across the whole system, tagged with the acting user and role. Credentials, tokens and passwords are redacted before anything is written. When something goes wrong, we can reconstruct exactly what happened.

Abuse limits are built in.

Rate limiting is applied per endpoint and tuned to how each one is actually used — a login attempt and a high-frequency location ping have very different profiles. Cross-origin access is restricted to known origins.

Consistency is enforced at the database.

Operations that touch multiple tables — check-out, bulk import, hierarchy reordering — run inside transactions. Partial writes don't happen.

Shared infrastructure across our products.

Our authentication SDK and communication service are used by every product we build. They arrive at TraceOn already hardened by other deployments.

What the admin portal gives you

Everything the field produces, in one place — scoped to whoever is looking.

monitoring

Live dashboard

Who's present, who's active right now, who's absent — scoped automatically to what the viewer is allowed to see.

map

Map view

The day's movement trail for any employee, plotted point by point in order, with one-click handoff to Google Maps for directions.

insights

Analytics over any date range

Attendance percentages, hours logged, session counts and average duration — plus gap analysis that surfaces unexplained breaks between sessions.

schedule

Time-slot report

Pick any set of times in a day and see, per employee, who was clocked in at each one. Filterable by branch, designation and reporting manager. Exportable to PDF.

account_tree

Interactive org chart

The full reporting hierarchy as a navigable graph.

calendar_month

Per-employee calendar & timeline

A month of attendance at a glance, and a session-by-session location trail for any single day.

group_add

Employee & structure management

Employees, branches, designations and hierarchy — including bulk onboarding by CSV upload with per-row validation and reporting.

download

Exports

CSV and PDF, because your finance team lives in a spreadsheet.

translate

Multi-language interface

Currently English, Hindi and Urdu.

Designed to fit into what you already run

Your systems stay the master. TraceOn adapts.

Your IDP arrow_right_alt TraceOn

Sign in with your existing credentials.

TraceOn can delegate authentication to a customer's existing HR or identity system on a per-company basis. Your employees keep one password, and you keep your existing user lifecycle.

Your HRMS arrow_right_alt TraceOn

Keep your HR system as the master.

A secured integration endpoint lets your HRMS push employee records into TraceOn — creating and updating people automatically as they join, move or leave. No double data entry.

CSV arrow_right_alt TraceOn

Or start from a spreadsheet.

Bulk CSV onboarding validates every row and reports exactly what succeeded and what didn't, so a failed import doesn't leave you guessing.

notifications_active

Notifications where they're needed. Push and templated email for onboarding, approvals, and attendance events.

We built the hard parts because the easy version doesn't survive contact with the field.

TraceOn is a product, but the reason it works is engineering: an offline-first capture pipeline, a battery-aware tracking strategy, tamper-aware data, and a permission model that mirrors your organisation.