Taming a Forecasting Web App

Something around a year and a half ago, I joined my current team at IBL Software Engineering as a developer. After a while, I was asked if I wanted to take over one of our older projects, and since it sounded like a challenge, I said, "Sure!"

17. 04. 2026
Zdielať článok

The project is egafor.eu, consisting of two parts: a publicly accessible Angular/NestJS application for viewing forecasts for general aviation over Central and Southeastern Europe, and a professional part designed for meteorologists, who use it as a collaborative environment for creating and adjusting forecasts. It had become a bit of a time capsule; because it lives in our company’s monorepo, it shares the codebase with modern IBL products, but the application itself had not been updated in years, except for a few small critical or security fixes. Once deployed into operations, the system proved to be stable and highly usable. Because it met users’ needs well, it did not require many custom extensions or significant changes for quite a long time. It was time to bring it into the present.

mapa - foto

Migration
Looking back, there were two main challenges when migrating the code to the latest IBL standards.

The first problem was that the application was living in a pre-strict world. Our current policy at IBL is to have strict mode enabled for all TypeScript code. So, the plan was to enable strict mode and try to compile. As expected, a sea of errors popped up. While most of them were quick fixes, some forced me to rethink the code logic. Instead of writing types such as string | undefined just to satisfy the compiler, it is often better to analyze the code flow and change it, if possible. By moving a check one level up—for example, wrapping a function call in an if statement—you can usually eliminate the undefined entirely. It makes your code much cleaner and easier to understand; great advice from our technical lead.

The second problem was related to UI errors. We use the Angular Material UI Component Library, and updating the version of Angular Material usually requires some code changes, but none of these had been done in eGAFOR. So, after I finally fixed all the type errors and opened the application, there were some "funny-looking" bugs, missing buttons, etc. But thanks to AI, it was quite easy to map the migration changes between the versions.

„Alternative Universes“ bug
The heart of eGAFOR lies in a place hidden from the public: the collaboration mode, where forecasters from multiple countries work together to create forecasts in real time.

Collaboration sessions are managed on the backend. The collaboration mechanism itself is provided by IBL&’s Visual Weather. When we were testing eGAFOR after the upgrade, we encountered a strange bug. After a while, users started seeing different realities (different forecasts), although they were supposed to be in the same session.

I remember spending days finding and analyzing this bug until I eventually traced it back to a Moment.js object used in the session creation. It turned out multiple sessions were being spawned because the reference time for the session was being mutated. The problem was that this object was used widely in the codebase, making it nearly impossible to find the exact line responsible for the change.

After some research, I decided to use a JavaScript Proxy object to trap and log exactly where the mutations were happening. A simple call to the clone function in the low-level code fixed the whole issue. I guess that is one of the reasons why Moment.js has fallen out of favor.

Below, I provide a simple example of an idea that helped me find and fix the bug.

kod2

kod-foto

Memory leak investigation
Once the upgrade was live, we hit a wall with a memory leak that only appeared in production under heavy load. You can’t fix what you can’t see, so I used the —inspect flag on our Node.js backend and tunneled via Chrome DevTools.

After analyzing the memory profile, I found that an RxJS ReplaySubject was the problem. All user actions were propagated through this subject, and that day I learned that using a ReplaySubject with an unbounded buffer can be really dangerous, since it cached every user action. The trick is to not use ReplaySubject, or use it with bufferSize or windowTime settings.

Beyond the Code
After the bugs were fixed and improvements implemented, I had the opportunity to meet with the forecasters—the people who use the application on a daily basis to keep pilots safe.

Seeing the software through a user’s eyes can be very helpful. I think it’s very beneficial for every developer to understand the user’s use case, as it can give your work true meaning.

So, there were a lot of lessons learned, but I am really thankful to IBL for this opportunity. I would encourage developers not to be afraid of legacy code or of change in general. Every challenge you take is an opportunity to learn something new and grow as a developer or even as a person. Especially now with AI, the ability to dive deep and understand a problem’s root cause remains a developer’s most valuable skill. Most things will eventually work out in the end,
and I am pretty sure we all love that feeling of satisfaction when it happens.

#bratislava #codecon #partners
Autor článku
IBL Software Engineering

Nezmeškaj aktuálne info o CODECON
Odkaz bol skopírovaný do schránky