Skip to content
Contact
Case Study · E-Mobility · Data

Charging & Electricity-Price App Built on AFIR/DATEX II Data

Real-time transparency for charging points and electricity prices (iOS & Android), built on official, AFIR-compliant DATEX-II data. Commissioned by a client in the e-mobility space.

.NET BackendLive PricingAFIR / DATEX IIKartendaten
Lade- und Strompreis-App von SB-Techworks: Kartenansicht mit Ladepunkten und Live-Preisen
500,000+App downloads
24 hResponse time (Mon–Fri)
100 %You own the code
1Point of contact, start to launch

The Challenge

The European regulation on the deployment of alternative fuels infrastructure (AFIR) requires that static and dynamic data on charging points — location, connector type, power output, availability, ad-hoc price — be published through official access points. What is served there is not a convenient REST API but DATEX II publications: a model-driven European standard built on deeply nested XML, with a very large number of optional fields and noticeable differences between publishers and between versions of the standard. Anyone who wants to surface this data in an app has to master the format first — the frontend is the easy part.

The second issue is volume and cadence. Inventory data typically arrives as complete snapshots at fixed intervals, while dynamic status information is published far more frequently. Handled naively, that means rewriting the entire dataset on every run without knowing what actually changed. Processing large volumes of data in a backend is less a question of more compute than of recognizing what is new and leaving everything else untouched.

Then there is the semantics. A charging site is a hierarchy of location, station, charge point and connector; identifiers have to stay stable across updates, otherwise points jump around on the map or show up twice. Prices are rarely a single number — they are assembled from energy, time and fixed session components. And with third-party data, "real time" is only ever as real as the publication cadence of the source. That belongs in the data model and in the UI rather than being rounded away.

The Approach

The architecture keeps three jobs cleanly separated: ingestion, a normalized core, and delivery. The ingestion layer pulls the DATEX II publications from the official sources, reads them as a stream rather than loading whole documents into memory, validates them against the schema, and translates them into a lean domain model of its own. The standard therefore stops at the system boundary — everything behind it works with clear, self-defined concepts.

The data backbone is a scalable .NET backend. The choice follows the nature of the work: schema-driven XML processed continuously. Static typing maps a model-driven format directly, the XML tooling supports streaming reads of large snapshots at a flat memory profile, and long-running background services with scheduled runs are first-class citizens. Ingestion and the delivery API scale independently, because their load profiles have nothing in common: ingestion runs in bursts dictated by the sources, the API follows user behavior.

Continuous market price updates run on their own cadence alongside the inventory data. Each run is compared against the last known state, so only genuine changes trigger downstream work — writes, cache invalidation, refreshing the map layer. Every record carries its origin and a timestamp with it. That is not cosmetic: it is the only way to show honestly in the app how current a value is, and to trace a complaint back to a specific source and point in time instead of searching the whole system.

On the client side, iOS and Android do not speak DATEX II — they speak a deliberately narrow API. Map queries are viewport-based, backed by a spatial index, and aggregated according to zoom level, so the amount of data transferred is tied to what is visible rather than to the size of the overall dataset. Real-time data in a mobile app therefore does not mean pushing everything to the device; it means serving exactly what each view needs, from prepared read models that still answer when an upstream source happens to be unreachable.

What Was Built

  • Real-time market prices
  • Continuous updates
  • Charging points on the map
  • Official AFIR/DATEX-II data basis
  • Scalable .NET backend

Technical Decisions

.NET for ingestion instead of a lightweight scripting stack

Node or Python would have produced a prototype faster, and Go would have been leaner for pure throughput work. .NET won because the bulk of the load is schema-driven XML processed around the clock: typed models generated from the schema, streaming parsers for large snapshots and long-running background services are standard equipment there rather than something bolted on. The cost is a larger runtime footprint than a compact Go binary — and schema-generated model classes that grow unwieldy.

A dedicated domain model instead of DATEX II all the way into the app

The alternative was to pass the standard model straight through to the API and the app: less mapping code, formally closer to the standard. Instead, a thin layer at the system edge translates once into domain terms, so differences between publishers and version changes in the standard stay contained in the ingestion layer and leave everything behind it untouched. The cost: that translation has to be maintained, and rarely used standard fields are deliberately dropped — if they are needed later, the layer has to be extended.

Scheduled polling with diffing instead of push all the way to the device

The obvious design would be to push status changes straight to the handset. But freshness is capped by the publication cadence of the source, not by the transport — a push does not make data newer than it was published. Scheduled polling with change detection, by contrast, is repeatable, traceable and survives an outage at one source. The cost is a delay that is inherent to the design, which is surfaced in the UI as an as-of timestamp rather than being sold as "live".

Precomputed read models instead of querying the raw dataset

Letting the app query the normalized dataset directly would have meant one data path fewer and always maximum freshness. For map views, though, it would have meant expensive geospatial queries per viewport, with costs growing alongside the dataset. Instead, read models are updated during ingestion and served per viewport and zoom level. The cost is additional storage and a second source of truth that has to be invalidated consistently — in exchange, response times stay independent of dataset size and upstream load.

Tech Stack

.NET BackendLive PricingAFIR / DATEX IIKartendaten

Outcome

Built for a client in the e-mobility space; the .NET backend runs continuously on a standards-compliant DATEX-II basis. Client-specific metrics remain confidential – what matters is the reliable, scalable data processing behind the scenes.

What This Means for Similar Projects

In projects built on official data standards, the effort almost never sits where the proposal assumes it does. The UI is the manageable part; the real work is in parsing, normalization, stable identity and change detection. The sensible move is to start working with actual publications very early rather than with the specification alone — divergence between the documented model and what is really delivered is the norm with standardized sources, not the exception.

The second transferable point concerns the word real time. With third-party data it effectively always means "as current as the source" — establishing that early saves you from architectural decisions that try to outsmart that limit. A system that carries the origin and as-of time of every value is considerably calmer to operate: reports of supposedly wrong data can be traced back to one source and one point in time instead of turning into a hunt across the whole system.

Frequently Asked Questions

What is DATEX II, and why does it matter for charging infrastructure?

DATEX II is the European, model-driven standard for exchanging traffic and mobility data, with corresponding publication formats for energy and charging infrastructure. AFIR is what makes it relevant: data on charging points is to be available through official access points, and that is the format it comes in — not as a proprietary REST API per operator. Anyone who wants to use that data has to be able to process the standard.

How do you process large volumes of DATEX II data without running out of memory?

The key is streaming parsing instead of holding whole documents in memory: records are read, translated and passed on one at a time. On top of that comes change detection against the last known state, so only deltas are written rather than the entire dataset. Ingestion and the delivery API run separately, so a large import run has as little effect as possible on the app's response times.

How current are price and availability data in an app like this, really?

Exactly as current as the source publishes them — a backend cannot make data fresher than it is delivered. The sensible approach is to carry an as-of timestamp per record and make it visible in the UI. That is not an admission of weakness; it prevents false expectations at the moment that matters, standing in front of the charger.

Why a .NET backend for this kind of data integration?

Because the work is schema-driven and continuous: typed models fit a model-based standard, the XML tooling is mature, and long-running background services are well supported. For short-lived, cold-start-sensitive functions a leaner stack would be the better choice — with a permanently running ingestion load, that drawback does not come into play.

What actually drives the effort in a project like this — the app or the backend?

The backend, by a clear margin. The app shows a map, a list and detail views; the complexity sits in the integration, format interpretation, normalization, stable identity across updates, and day-to-day operation. Estimating effort by counting screens systematically underestimates projects of this kind.

Can a data foundation like this be used without a dedicated app?

Yes. The ingestion and normalization layers are independent of the client device — the mobile app is just one possible consumer among several. A web view, an internal analytics dashboard or a separate interface can all sit on the same normalized dataset without building the data integration a second time.

Planning something similar?

SB-Techworks builds custom apps for iOS and Android – from MVP to scalable business app, straight from development. You get an honest assessment of feasibility and cost within 24 hours (Mon–Fri).

Request a free assessment  custom app development →