Darko Pavic - Global Retail & Fiscalization Expert

What It Takes to Build a Reliable Android Fiscalization App

Loading the Elevenlabs Text to Speech AudioNative Player...

Practical lessons from production on software architecture, background execution, transaction integrity and country specific fiscal rules

At our Retail Compliance Forum on 29 October, we asked Boris, one of the developers working directly on our Android fiscalization application, to explain how the project moved from an idea to a product used in production. I particularly wanted the discussion to come from the engineer doing the work. Technical decisions look quite different when you have to maintain the software, support another country and make sure that a transaction is processed correctly every time.

The central lesson was surprisingly simple. An Android device can run a fiscalization service, but Android was designed around the needs of a mobile user, not around an application that must behave like an always-available fiscal server.

Solving that conflict has consequences for architecture, testing, data storage and day-to-day operations.

A proof of concept is not a production architecture

We did not start this project with a complete Android platform and a long list of supported countries. We started by testing whether fiscalization could work on an Android device at all. An external development partner helped us build the proof of concept for France. Once it showed that the approach was feasible, we brought the development and the fiscalization knowledge together inside Fiscal Solutions. Boris joined the work as the project moved toward its first release.

That first version was not perfect, and Boris was open about it during the forum. The immediate objective was to accept a fiscalization request and return the expected result. It did that. But the next questions were more difficult. How do we add Austria or Germany without creating a tangled codebase? How do we change a certified implementation safely? How do we know a service that works in a development environment will behave correctly after days of use on a real device? After France came work for Austria and Germany, and at the time of the forum the team was also focusing on the Czech Republic.

I think this is an important distinction in software development. A successful proof of concept proves feasibility. It does not prove that the architecture is maintainable, that changes are safe or that the application is ready for a large retail installation. Those are separate engineering tasks.

The POS should not care which platform processes its request

Before Android, we already had fiscal services operating in Windows, Linux and cloud environments. Those solutions used .NET technology. Our objective was not to expose an entirely new interface simply because the underlying device changed. A POS vendor should be able to use the same fiscalization API and expect equivalent behaviour from the service for the same country and transaction, whether the implementation is local, in the cloud or on Android.

This created a difficult technical requirement. Our existing applications behave like HTTP services: the POS sends a request, the service processes the transaction and returns a response. On a desktop or server, keeping such a service available is a familiar task. On Android, the application lifecycle is controlled much more aggressively by the operating system. We could preserve the API contract, but we could not simply reuse the desktop codebase unchanged. We had to reproduce the expected service behaviour using a different platform architecture.

For retailers and POS vendors, that separation matters. If the interface stays consistent, one integration can support several deployment models. But consistency at the API level should never be confused with identical implementation effort underneath it.

One shared core and a separate application for each country

Our first implementation for France naturally contained code written for that specific country. When we considered adding more countries, we had to decide what belonged to the common platform and what had to remain inside a national module. Many functions are shared: receiving and validating requests, local storage, configuration, monitoring and synchronization. The fiscal rules differ.

The team began extracting a common core with defined interfaces and moving national logic into separate modules. The dependency is deliberately one-way. Country modules depend on the core, but the core should not need to know whether the module is for France, Austria or Germany. That makes a change in one market less likely to affect a different one. As Boris explained, this refactoring is still an ongoing engineering task, not something completed in a single sprint.

There is another decision that may surprise customers. We do not distribute one APK containing every country. We build a separate installation package for each country by combining a particular core version with the relevant country module. It would be more convenient in some circumstances to install one package everywhere and select the country in the settings. We chose the additional packaging work because we want better isolation, version control and visibility into exactly which code is installed. A change needed for Austria should not introduce a risk into a French installation.

This decision also affects release management. Each package must be built, tested, validated, signed and versioned. In a regulated environment, knowing which core and country versions were delivered to a specific installation is part of maintaining control of the software.

Android is not designed to keep a fiscal server alive

One of the most useful parts of the forum was Boris’s explanation of Android background execution. A normal mobile application may be stopped when the device needs memory or battery power. The user usually notices very little. For a fiscalization service, however, the POS may be waiting for a response when this happens. An interrupted fiscal transaction has very different consequences from a music player stopping in the background.

The Android implementation uses a foreground service to keep its request-processing component active with a higher operating-system priority. It also includes monitoring and recovery mechanisms, described in the forum as a watchdog, to restart the service if necessary. The service is designed to become available again after a device restart as well. These mechanisms reduce the risk of interruption, but they cannot remove the operating system’s control over the device. Boris stressed that the team had not encountered such a service interruption in production at the time of the forum; the recovery paths were nevertheless designed and tested for it.

The team also checks operating-system settings that can affect reliability. Battery optimization, notifications and permissions relevant to background execution require attention. New Android versions may change how these features work. Consequently, supporting Android means testing operating-system updates and device behaviour over time, not merely testing a fiscal API once and declaring the work finished.

Transaction integrity must survive an interrupted process

Keeping the service running is only part of the problem. The more important question is what happens to a transaction if the process stops at an inconvenient moment. Boris described an approach in which requests are processed and their data stored locally, with controlled transaction states that help protect processing and sequencing from an interruption. Stored information can then be synchronized with the company’s cloud services when the service is available.

The engineering principle is worth remembering: the application must be designed on the assumption that an interruption can happen. A foreground service reduces its probability; persistent local state and recovery mechanisms address its consequences. These are not interchangeable safeguards. A POS integration also needs to know how to handle a delayed response and how to determine the state of a transaction before trying again.

There is an operational detail here that is easy to miss. An application upgrade and deliberate removal of application data are not the same event. The team designed for records to survive normal updates, but uninstalling the application or wiping its data can destroy locally stored information. The Android application therefore warns users about risky actions and monitors configuration conditions that could threaten reliable operation. In retail, protecting data from accidental operational mistakes is just as practical a concern as protecting it from software defects.

Offline capability depends on the fiscal law

During the questions, someone asked whether the Android service needs an internet connection. Boris’s answer was precise: it depends on the country. The application has an offline-first design and can continue processing without a connection where the applicable fiscal rules permit offline operation. Initial configuration and certain communication steps still need connectivity. We should not confuse a technically possible offline transaction with one that is legally permitted in every jurisdiction.

This is especially relevant for mobile POS devices and shops with inconsistent connectivity. Offline support requires local persistence, later synchronization and a clear understanding of the country’s permitted operating modes. A technical design must follow the law, rather than assume that the same offline behaviour is appropriate everywhere.

Testing revealed a fiscalization assumption we had missed

Boris shared a small example that says a great deal about domain knowledge. During testing of the French implementation, the team discovered that parts of the software assumed amounts would always have two decimal places. A test with three decimal places was enough to expose the problem. The issue was found in testing, before it caused harm to customers.

An experienced developer may reasonably start with two decimal places because that is common in everyday payments. Fiscal rules and transaction data do not always fit such assumptions. This is why engineers need close access to people who understand the regulatory domain, and why automated tests must include cases that appear unusual from a general software perspective.

The proof of concept also began without the depth of automated tests the team needed for long-term maintenance. Before larger refactoring, developers worked to lock in the existing behaviour and change the structure in small, testable steps. The current process includes unit, integration, end-to-end and manual testing. I found this admission valuable because it reflects a normal development reality: the work that proves an idea is possible is different from the work that makes the product dependable.

Operations and deployment are part of the product

Some useful improvements are less technical but immediately visible in stores. Boris described how a device can be configured by scanning a QR code rather than entering settings manually. That may seem like a small feature until a retailer has to provision a hundred tills. At that point, the time and error risk associated with manual configuration become important.

The team is also evaluating whether an iOS version would be practical, but no implementation commitment was made during the forum. The operating-system constraints are different and would need their own technical assessment. I would be cautious about presenting mobile fiscalization as a simple matter of rebuilding the same screen on another platform.

What I took from the discussion

I opened the forum with a look back at POS technology from the late 1990s. We have moved from large terminals and fiscal printers to smartphones, cloud services and mobile checkout. Yet many of the basic fiscalization concerns remain familiar: understanding the rules, protecting transaction data, passing certification and supporting audits. What has changed dramatically is the environment in which developers must meet those obligations.

Boris’s presentation reminded me how much of the real work remains invisible to the retailer. The customer sees a completed sale and a receipt. Behind it are decisions about operating-system lifecycle, country isolation, transaction state, testing and recovery. The most useful discussions about retail compliance are often those in which the engineer who made these decisions explains what worked, what failed in testing and what still needs to evolve.

That is the purpose of our Retail Compliance Forums at fiscal.community. We want to share practical experience from people who work with the problems themselves and give retailers and POS providers an opportunity to ask detailed questions. I hope these engineering lessons are useful to anyone building or integrating fiscalization software, on Android or on another platform.

Source

Retail Compliance Forum, “Building a Fiscalization App for Android From Requirements to Production”, 29 October 2026. Presentation and Q&A with Boris, Fiscal Solutions development team.

Darko Pavic

Darko Pavic is a retail technology and fiscalization expert with more than 28 years of experience in international POS systems, retail compliance and software architecture. His current work focuses on fiscalization, e-invoicing, compliance intelligence, machine-readable regulation and the responsible use of AI in compliance-critical systems.

https://darkopavic.xyz