Overseas
Azure and integration architect
Distribution for tax-free shops at airports and on cruise ships. A team of three, two of us developers, so the work here does not divide into neat roles.
Bluebird · from a weekly price mail to the B2B web shop
It started as the weekly price-change mail. Sales sees the coming changes on Tuesday and can still intervene, customers get the new prices on Thursday. That foundation became Bluebird, the B2B shop most Overseas customers order through today, replacing a Python version that had reliability problems. Angular front end, ASP.NET Core API, orders landing in the ERP. It ran on our own servers first and moved to Azure later. After the Business Central migration the price sync moved to Azure Functions and runs in two steps over two queues: one message per customer to fetch prices, then the result onto a second queue that writes to the database. Splitting it there is what buys both the throughput and the reliability, because a failure retries one step instead of the whole run.
Overseas Integration Platform
Once Bluebird stood, I started replacing the many separate applications that talked to Navision directly. Some were Python, others were built inside SQL itself, and nothing was shared between them. The platform reuses what Bluebird already had, the ERP sync above all. It is a message-based SOA on NServiceBus with three endpoints: one for Business Central, one for outbound messages and one for inbound. The two message endpoints speak whatever the other side speaks, REST, FTP and XML among them. The endpoints are hosted as Windows services on our own servers, which is where this one stays. One plugin per integration, each in its own folder with its own assemblies, so a new flow ships without touching what already runs, and the deployment pipeline follows that same structure. It replaced Boomi. Reliability was the whole point, and the messaging is what buys it. Anything that fails on a temporary cause stays put and can be replayed once the cause is gone, whether that was a database connection that dropped or a bug we only fixed the day after. Nothing is lost because a system happened to be down at the wrong moment. When something does fail the developers get a mail with the diagnosis, usually before a user has noticed.
Projects hanging off the platform
Over a dozen integrations run on it as plugins: EDI, WMS, OrderEye, Slim, Multiscan, Rio, Entra ID sync for external BI users, Jira ticket creation, warehouse scan, bank statement scan, Stream, Zetes, ASN export, and more since. Multiscan is one of the more physical ones, a device that measures items in three dimensions, with a Blazor screen in front of it and a Python solution behind it that it replaced. Each of these is a plugin rather than one more application with habits of its own.
Navision to Business Central online · live 2025
Drove the migration end to end and did the AL extension work inside Business Central as well as the .NET side. Six companies run on it today. A SaaS tenant has no back door, so every integration had to move onto the official APIs. That rework landed without a functional freeze, because the endpoints were already isolated behind their own contracts. The migration is the clearest return I have had on architecture that was set up years earlier.
Document recognition · where it started
Warehouse documents first. Find the barcodes on a scanned batch and split it into separate documents along them. Bank statements came next and asked for more: extract enough from each page to file it against the right bank account. A few thousand of those two in total. Between them they are where we learned how extraction actually behaves, which is what made the next one affordable.
OrderEye · sales and purchase documents
Built on what the warehouse and bank statement work taught us, with Azure AI Document Intelligence doing the reading. On the sales side it creates the sales order in Business Central and reports back to the customer every line where the price in their own document differs from the real price in BC. On the purchase side it checks what the vendor sent against what BC holds. The user sees at a glance which lines disagree and corrects them by hand, and those corrections go back to BC. Business Central keeps a trace of everything OrderEye handled. A few hundred invoices a month go through it. It does not run the other two extractions, it inherited their principles.
- Bluebird and the integration platform share a large body of code through internal NuGet packages. One uniform way of working covers everything built here, so a fix in a shared library arrives in both. Both sit on .NET 10 today, migrated up from 8.
- Set up Azure DevOps and the release pipelines for both applications. Staging runs on our own servers for both. In production only Bluebird sits on Azure, the integration platform stays on premise.
- Observability follows that same split. On premise a middleware catches the logging and the unhandled exceptions, and it is that middleware the developer mails come out of. What runs on Azure reports into Application Insights. Every API is described in Swagger.
- The code follows OWASP, and the secrets sit in Key Vault instead of in configuration. Personal data falls under GDPR, so anonymisation is designed in wherever the data does not need to stay identifiable.
- Alongside the development work I administer the Azure environment: the resources, the users on the tenant, the cost, and the support when somebody cannot get in.
- Gave the training when the platform was new, and I review the technical design choices of the other developer.
- Per environment a different object graph in the IoC container, so staging and production differ in configuration rather than in code.
.NET 10, ASP.NET Core, Blazor, Business Central (AL), Azure App Service, Azure Functions, Azure Storage queues, Azure Blob storage, Application Insights, Entra ID, Azure AI Document Intelligence, NServiceBus, EF Core, SQL Server, Angular, REST, Swagger, SOAP, FTP, XML, Azure DevOps, OAuth 2