Eleven years of Bandwidth Monitor: An indie journey (Part 3)

This is the final Part 3 of the blog series in which I reflect on eleven years of work on Bandwidth Monitor. You can find Part 1 here, which goes into detail on how it started, or go to Part 2, which covers the changes of version 2.

In this part, I’ll describe the work that went into version 3.0 — especially monetizing the app — the versions afterwards, and where I see the app heading in the future.

The big version 3.0 release

The big move to version 3.0 came in October 2024, roughly nine months after version 2.2 released. The work on this version started over a year before, in August of 2023. This version was another rewrite that took an entire year with around 400 commits. When it was released, it featured all the latest and greatest tools that Apple platforms had to offer.

It included major new features: the adoption of Swift Charts, which also allowed for graph widgets for the new iOS widget system, German localization, new customization settings, and an entirely new architecture that replaced UIKit with SwiftUI for navigation using NavigationStack. SwiftUI had previously been used for views only, and now the entire app was adopting the SwiftUI lifecycle. This allowed me to migrate to a modern architecture for improved performance and developer ergonomics. To support these new features, I was required to bump the minimum supported iOS version to 17.0.

At the same time, I took a bet on SwiftData as the foundational data storage engine for Bandwidth, replacing my hand-rolled JSON blob file. It had some problems early on but I wagered they would be resolved in time. This is a bet that has unfortunately not paid off. Overall, I had to manually move a lot of processing into the background to keep the UI responsive and in a consistent state.

Learning: Don’t build the foundation of your app upon promises of future developments — let them materialize first.

Replacing DGCharts with the new Swift Charts framework was a great success. It had more features and was easier to use in a SwiftUI app. Conceptually, it fit well into how the new app architecture was built and generally felt more at home on iOS 17. I could quickly iterate on the design of these charts and find a look for the graphs, axes and descriptions that made the app look much more modern than before.

Using these new declarative charts provided the opportunity to reintroduce widgets as well. However, these work differently than I would have liked: the update mechanism queues updated data ahead of time and doesn’t work well with the live data that the widgets are supposed to show.

Underneath, I introduced a modular architecture for better reusability of the app’s codebase. Starting development with it is hindering progress until a certain point — at which point having a modular architecture helps with build times and general efficiency.

Learning: You need to keep looking for the point when the switch to a modular architecture makes sense for a product, and then go all in.

The decision to monetize the app

During the major reworks of version 3.0, I started thinking about introducing a Pro tier. Primarily, it is meant to recoup roughly a decade of development costs, not to build a business. I wasn’t against getting a bit of money for the time I had poured into the app over the years, but realistically it has always been too niche to really provide any substantial amount of income.

Historically, I had been paying the $99 developer fee since the beginning for the privilege to even develop on my own iPhone. Apple has since relaxed this requirement and you can now start developing on your own device free of charge. This meant that by 2024, I had already paid almost $900 to Apple, not considering the time spent on development.

I decided in favor of the Pro tier to (a) gain the experience of using raw StoreKit myself, and (b) have a clear path for users to give back some money in exchange for value that they would get inside of the app.

I learned a lot from my early pricing mistakes based on wrong assumptions, and am thankful to be at a point where my users are paying a fair price for the Pro tier. Bandwidth is still not an app that can pay for my bills, but at least it is slowly recouping my expenses of the past decade.

Thanks to everyone sticking with Bandwidth during this rough first introduction.

Versions 3.1–3.3

Afterwards came a time of reaping the benefits of the new architecture.

Version 3.1 introduced a network debugging tool, added Audio Graphs support, and brought a lot of performance improvements under the hood. It also updated the colors of the app to be more closely aligned with the new FRITZ!OS 8.20 release of the Online Monitor design.

Modern Online Monitor

The current iteration of the Online Monitor since FRITZ!OS 8.20

In September 2025, version 3.1.3 added initial support for iOS 26 by updating the app icon and system toolbars for Liquid Glass.

Liquid Glass app icon

Liquid Glass app icon

Version 3.2.0 brought more improvements to StoreKit’s transaction handling, the UI layouts, accessibility settings, and the option to cancel the subscription directly within the first 14 days after subscribing.

The current version 3.3.0 features significant performance improvements that increase the frame rate and reduce power consumption. Under the hood, the entire app is now compiled in Swift 6 language mode for added compiler safety. You can read through details on this in the announcement post.

Bandwidth’s future

Since the beginning, I always had more ideas for Bandwidth than time to implement them. This hasn’t changed — at the time of writing, there are 44 issues of varying size open that I’d like to work on. You’re always welcome to send me feedback and suggestions that I can incorporate.

I alluded to a few in the 3.0 announcement post, and while these items are not on a set roadmap, I’d personally like to see the following points implemented at some point:

  • Live activities for near-realtime data on the lockscreen
  • Native macOS, watchOS, and tvOS apps
  • Shortcuts support for automation
  • Configuration editing
  • Control Center support
  • Certificate pinning for improved SSL/TLS support

A note on the use of AI in Bandwidth

With recent advancements in AI coding tools, I have used them more and more to help with the development of Bandwidth as well. 3.3.0 is the first version to contain AI-generated code.

While I am generally skeptical of using AI too much, the tools have become very helpful in the workflow of a solo developer. They provide different ideas and can cross-check implementations. Even if the results are provably wrong, I get some feedback that I simply didn’t have before. Maybe it’s an idea that nudges my thinking toward the right solution.

It is important to note that I do not use AI to “vibe code” the app: instead, I provide the architecture and have a clear goal in mind before prompting it to help out. I read through the documentation myself to understand what would roughly be the important bits to look out for. This allows me to review every single line of generated code and make sure the changes are what I was expecting.

In 3.3.0 specifically, AI helped a lot with looking through performance traces and identifying the issues I was seeing. Doing these optimizations has been in the back of my mind for a long time, but using AI allowed me to spend significantly less time finding the culprit and instead thinking about solutions to the problem.

Additionally, AI writes unit tests to avoid regressions in the future — something I’d never have made the time for otherwise.

Learning: Adopting AI with a clear idea of its capabilities and a clear goal in mind, and reviewing its changes carefully — while still owning the code — can help speed up development.

Closing

Thanks for reading this extensive, three-part story of Bandwidth’s journey so far. I appreciate you taking the time to read it all, and am happy to receive feedback on what you thought.

I am looking forward to working on version 3.4 and beyond!

Sören