Issue #2: Betas, Alex Chown, and the Retroactive Attribute
A new kind of iOS dev newsletter that breaks out of the main thread
Delivering a Great Beta Experience
A beta test is more than just a way to catch bugs before launch. It’s a vital step in making an app that users actually want. Sure, internal testing can iron out obvious issues but real-world use can reveal the friction points, crashes, and UX challenges that only surface when actual users get their hands on your app. Users have this incredible knack for breaking your code in ways you never thought possible. A well-run beta doesn’t just improve stability; it helps you refine the experience, validate key features, and even build an early community of engaged users.
In this issue of Kernel Extension, we’ll break down how to run an effective beta, from selecting testers to collecting feedback and making data-driven decisions. It doesn’t matter if you’re preparing your first launch or refining a major update, the insights you gain from a well-executed beta can set your app up for long-term success.
More Than Just Bug Hunting
Many people see a beta as nothing more than a way to catch bugs before an app goes live, but there is so much more beyond that. A beta is also an opportunity to evaluate the overall user experience, identify pain points, and confirm that your app’s core features work as intended in real-world conditions. Even the most polished app in a controlled environment can behave unpredictably when put in the hands of diverse users with different devices, usage patterns, and expectations.
Beyond technical improvements, a well-run beta provides valuable insight into how people actually use your app. Are they engaging with the features you thought would be most impactful? Are they confused by any parts of the interface? Do their actual workflows align with what you envisioned? These are the kinds of questions that only a beta can answer, helping you refine both the functionality and usability of your app before it reaches a wider audience.
And lastly, a beta is a wonderful tool for building an early community around your app. Engaged beta testers can become some of your most loyal users, offering word-of-mouth marketing and even acting as advocates for your app after launch. When users feel like their feedback truly means something, they’re more likely to invest in the app’s success, giving you insights that go beyond bug reports to help you shape an app that really resonates with your user base.
Setting Up for a Successful Beta
A great beta starts long before you invite your first testers. I’ve seen so many betas become a flood of disorganized and in-actionable feedback. Proper planning can alleviate this. The first step is defining clear goals: What do you want to learn from your beta testers? Are you primarily looking for bug reports, usability feedback, or views on how people interact with your main features? Having a focused objective will help you structure your beta program effectively.
Next, picking the right testers is crucial. Sure, you could throw your TestFlight link out to the world and get as many people as possible. And while that might be tempting, a smaller, more engaged group can often provide better feedback than a massive, unfocused audience. Think about recruiting a mix of technical and non-technical users, as well as people who match your ideal target audience. If your app is designed for productivity enthusiasts, for example, having a group of testers who already use similar tools can provide more relevant insights.
Finally, communication is key. Make it easy for testers to provide feedback by setting up structured channels. This could be a dedicated TestFlight survey, a private Discord server, or a simple email form. In the past, I’ve used a separate public GitHub repo and let users create Issues and it’s worked quite well. They make it trivial to setup templates that allow users to provide structured feedback. In any event, let testers know what kind of feedback is most valuable, provide guidance on how to report issues, and most importantly, show appreciation for their time and input. A successful beta isn’t just about testing software. It’s about engaging real users in a way that benefits both them and your app’s future.
Gathering Useful Feedback (Without Overwhelming Testers)
Getting feedback is one of the biggest benefits of running a beta, but not all feedback is created equal. Without a clear system in place, you can quickly end up with a chaotic mix of vague complaints, one-off suggestions, and reports that lack anything actionable. The key to making feedback hit hard is guiding testers on how to provide it effectively while making the process as frictionless as possible.
Start by setting expectations. Let testers know what kind of feedback you’re looking for whether it’s general usability issues, bug reports, or feature-specific insights. Giving testers a structure to follow, such as a short survey or a form with specific prompts, ensures that you get detailed, helpful responses instead of generic comments like “it’s broken” or “this doesn’t feel right.”
You also want to make it easy to submit feedback. Some developers prefer TestFlight’s built-in feedback tools, while others set up dedicated Slack or Discord channels, GitHub issues, or even simple Google Forms. Whatever system you choose, the goal is to lower the barrier to entry so that testers can report issues quickly and easily. Screenshots, screen recordings, and device logs are incredibly helpful, so encourage testers to include them whenever possible. I’ll be candid and tell you that no matter how much you prep your users, there will always be those that don’t pay attention or simply don’t care enough to do it the way you hoped. Take those with a grain of salt and focus on the ones that you can operate on.
Finally, strike a balance between engagement and overload. Too many requests for feedback can burn testers out, while too little communication can make them feel ignored. A simple check-in every week or two can keep testers engaged without overwhelming them. And when someone takes the time to submit thoughtful feedback, acknowledge it. Even a quick “Thanks! This is great info” can go a long way in keeping testers motivated to contribute. A well-structured beta doesn’t just generate useful data; it builds a stronger connection between you and your future users.
Analyzing Beta Data
OK so you’re getting feedback. Now what? Once the info starts rolling in, the real work begins. I know I’ve said it already but it’s worth repeating — a great beta isn’t just about collecting feedback. It’s about making sense of it. Not every issue reported will need immediate action, and not every suggestion will fit your vision for the app. Some of them will be completely bonkers and nonsensical. Knowing how to sort, prioritize, and act on feedback is what separates a productive beta from an overwhelming one.
Start by categorizing feedback. Divide reports into clear groups: bugs, usability issues, feature requests, and general observations. Bugs should be further broken down by severity with crashes and major functionality failures obviously taking priority over minor UI quirks. Usability issues, like confusing navigation or unclear UI elements, are just as important as technical bugs since they directly impact how users experience your app.
Look for patterns. If multiple testers mention the same problem, that’s a clear signal that it needs attention. One-off reports might still be valid, but if only one person is struggling with something, it’s worth considering whether it’s a niche issue or an outlier. Feature requests will be tricky. Some will be great ideas that align with your app’s goals, while others may be personal preferences that don’t fit the bigger picture. Others will be totally bewildering how someone could craft it. Always evaluate whether a request improves the experience for your target audience, rather than just one individual.
Data matters, but so does intuition. Metrics like crash reports, retention rates, and session duration can provide solid ideas into how your app is performing, but don’t ignore qualitative feedback. A beta tester saying, “This feature feels frustrating to use” is just as important as a performance metric showing slow load times. The goal isn’t just to fix what’s broken. It’s to refine and enhance the app experience as a whole.
Lastly, know when to stop. No app is perfect, and chasing every last bit of feedback can lead to endless delays. A good beta helps you get your app to a point where it’s stable, clear, and ready for launch—not flawless. Use the feedback you’ve gathered to make meaningful improvements, then set a cutoff point where you transition from fixing issues to finalizing the release. At the end of the day, shipping a solid product is better than endlessly tweaking in pursuit of perfection.
Wrapping Up Your Beta and Preparing for Launch
As your beta period comes to an end, it’s important to transition from testing to launch mode. This is when you make sure your app is polished, stable, and primed for a successful release. Wrapping up a beta the right way also sets the tone for how your early users perceive your app and whether they’ll stick around after launch.
Start by thanking your testers. They took time to use your app, find issues, and provide feedback, and a little appreciation goes a long way. A simple thank-you email, a shoutout in release notes, or even free access to a premium feature (if applicable) can make testers feel valued. Engaged testers are more likely to become long-term users and advocates for your app.
Next, document the key takeaways from the beta. What were the biggest improvements made based on user feedback? What areas still need attention in future updates? Not every issue has to be resolved before launch, but having a clear post-launch roadmap helps you not lose momentum. If there were any major requests that didn’t make it into the initial release, consider sharing a high-level plan so users know what’s coming next.
And last, make sure your launch strategy is in place. Your beta has helped refine the product and now it’s time to focus on visibility. Are you leveraging your beta testers as early promoters? Do you have a solid App Store listing with a compelling description and screenshots? Are you reaching out to press, communities, or influencers in your niche? A smooth transition from beta to launch can maximize the impact of all the hard work you’ve put into your app.
Final Thoughts
A well-run beta test is one of the most valuable tools you can have as an indie developer. It’s more than simply debugging. It’s a chance to improve user experience, validate key features, and build a community of engaged users who can help shape the future of your app. When done right, a beta doesn’t just lead to a better product; it builds trust, loyalty, and momentum for launch day.
If you’re preparing for your own beta, start with clear goals, the right testers, and a structured approach to gathering feedback. Make it easy for users to share insights, keep them engaged without overwhelming them, and most importantly, act on the feedback they provide. Every piece of input is an opportunity to refine your app into something truly great.
I regularly post my thoughts on Twitter. Follow me for more content that didn’t make the article!
Indie Spotlight: Alex Chown
In each issue of Kernel Extension, I feature an indie developer and their journey to the App Store. I dive into their stories, their struggles, and what drives them to build. It’s not just about the apps, they’re great, but the people behind them are even more fascinating. Let’s take a look at this issues Indie Spotlight.
Many indie developers start as programmers, but Alex took a different path. A designer first, he never saw himself as a “real developer”. Even now, he hesitates to claim the title. But after building his first app, Bosh, he proved that what matters isn’t what you call yourself; it’s what you create. In this issue’s Indie Spotlight, I sat down with Alex to chat about his journey from designer to developer and how he brought Bosh from paper to pixel.
From Apple Enthusiast to Designer
Alex’s journey into app development hasn’t been a straight path, but instead more of a winding road shaped by a deep admiration for Apple and an unshakable curiosity. Long before he wrote his first line of Swift code, Alex was captivated by the craftsmanship behind Apple’s products. “I’ve always been a big fan of Apple. Basically Steve Jobs, all of that era”, he told me.
Alex’s early experiences with the Apple ecosystem started while he was working for an Apple Premium reseller in England. Fresh out of school, and with the encouragement of his dad, Alex boldly emailed the manager and told them “I think I should work in your store.” And, it worked. He landed the job and spent nearly 5 years there engrossing himself in all things Apple. While working there, Alex won a Shot on iPhone photography competition hosted by Apple. The award was more than merely a recognition of his skills, but a validation of his ability to create something that resonated.
Then came a pivotal moment. Without warning, the reseller made Alex redundant at work (“laid off” for those of us in the US). His survival was on the line and only he could be the one to claw it back. He needed something of his own; something he could use to forge his own path. And so, he created iHelp — a website that would serve as his own Apple support business for many years to come.
Alex later went on to work at Bang & Olufsen, which allowed him to continue running iHelp at the same time. One day, out of the blue, he got a call from a customer back in his reseller days. They created a local startup and felt Alex could have a massive impact on their products. Alex left Bang & Olufsen to join the startup where he was tasked with contributing to an upcoming flagship app, Orbzii. This is where his design adventure took shape. Alex always felt he had an eye for what design looked “right” but he never had the opportunity to put it to practice on such a large collaborative project. When his new team handed him the design files for Orbzii, Alex immediately saw the opportunity in front of him. “I could do this”, he told me. “I didn’t even know about Figma. But, I felt confident I could download these programs and give this a go, like, I’ve always wanted to, I’ve always had the art, if that makes sense.” And, give it a go he did. His work was fundamental to Orbzii and opened up an entire world of design for him to run with.
I've just chucked myself in the pool and just tried to swim and figured out that I know how to swim - Alex Chown
Wanting to have a bigger impact, Alex secretly assembled wireframes for another app the company was building, Pogo. He spent his spare time working in the shadows building a prototype to nail down the user experience. “I just do things”, he described. When he felt it was ready, he called his boss into the lounge and watched him interact with the prototype. “I think he swore at me. He was like ‘this is fucking incredible.’” Alex realized he was onto something telling me “I've just chucked myself in the pool and just tried to swim and figured out that I know how to swim.” To this day, Alex’s designs are still influencing the shape of Pogo and over 60,000 people get to see them every day. But it wasn’t enough to only design. Alex wanted to go further.
The Birth of Bosh
This is where Alex’s story takes an unexpected turn; one that would redefine his view of app development, challenge his imposter syndrome, and introduce him to a tool that would change the way he worked forever.
If you’ve ever downloaded a to-do list app, you’ve probably experienced the same cycle: you add tasks, complete a few, and then forget about the rest. Days or weeks later, you open the app only to find a mountain of unchecked tasks staring back at you, untouched and overwhelming.
Alex had been there. He had tried every productivity app he could find, but they all shared the same flaw; they let you procrastinate. He wanted something different, something that would force accountability. At first, the idea of creating his own app felt out of reach. He had dabbled with a bit of code but not enough to feel comfortable building a full-fledged app. But over the years, that mindset started to shift. In the back of his head, a seed had been planted for a new kind of to-do app that would eventually grow into Bosh.
Unlike traditional to-do lists that let tasks sit indefinitely, Bosh operates on a time-sensitive system. If you don’t complete a task by the deadline, it’s gone. No backlog. No clutter. Just a clean slate. It is a system built around commitment and urgency, making sure that what you write down actually gets done. Failing to complete tasks breaks your streak resetting you back to square one. But while the idea was clear, turning it into a real, working app was another challenge entirely. He had the vision, the design skills, and a deep understanding of user experience. What he needed was the technical ability to bring his ideas to life.
An Unexpected Development Partner
By now, Alex was a pro at designing apps, but he hadn’t built one himself. With Bosh, he set out to change that. He started where he was most comfortable: Figma. The entire concept for Bosh took shape visually first. Every button, every interaction, and every tiny animation was meticulously designed before a single line of code was written. This design would sit idle for a year while Alex faced the next challenge: how do you turn a design into a working app when you don’t consider yourself a developer?
That’s where AI changed everything.
For Alex, AI wasn’t a replacement for development skills. It was a tool to bridge the gap. He discovered Cursor, an AI-powered coding assistant that helped him translate his designs into SwiftUI components. At first, it felt like magic. He was able to take a screenshot of his Figma project and feed it to Cursor. “It was just nuts, man,” Alex explained. Alex could then drop the suggested code into Xcode and see it run. “For a few good nights, of sleepless nights, I managed to build it,” he told me. “I won’t lie. I was emotional. I was actually so proud.” The experience was eye-opening. Instead of spending months learning to code from scratch, Alex could focus on refining the experience, making sure every detail from animations to haptics felt just right. But AI wasn’t perfect.
The Hardest Part of the Journey
Every indie developer faces at least one major challenge; the kind that makes them question if the project is even worth finishing. For Alex, that moment came when he ran into technical roadblocks he couldn’t immediately solve. “I had a very big issue with what I call the window”, he told me. “It’s kind of like a window into your tasks.” Alex wanted to extend the capabilities of this window so he turned to his AI development partner to try tackling it but the tool couldn’t get it right. It often returned inaccurate results or simply didn’t understand the problem at hand.
“Some of the [Xcode] build failures, I couldn’t understand,” he said. Alex would copy the errors into Cursor to try making sense of them but that only made it worse. The tool would come back with unhelpful results or a completely wrong interpretation altogether. “That was probably the most frustrating thing is working around things that I don’t know like how to fix,” he told me. “Asking it [Cursor] to fix it, it thinks it’s fixed it, and then we end up going in a loop.”
I want to highlight how Alex uses “we” here. I get the sense that Alex felt Cursor truly was his development partner and that they were in this journey together. During particularly difficult debugging sessions, Alex found himself muttering words of encouragement to will Cursor into finding the right answer. “You can hear me, how I talk about it now” he said. “Sometimes I would be like ‘Come on! You can do it!’”.
Eventually, Alex figured out the issue, but not by relying on AI alone. He had to develop his own understanding of the problem to find a working solution. Alex felt himself learning, thanks to AI. The loop of asking, testing, and troubleshooting was infuriating, but it also pushed him to dig more. Instead of blindly accepting AI-generated solutions, he started breaking down errors himself. He learned to ask better questions, refine the suggestions, and build up his own understanding of the code along the way. And with that, Bosh went from concept to reality.
AI as a Replacement
The software industry remains divisive on AI with many developers claiming using it means you’re not a “real” software developer. I asked Alex if he thought Bosh would have come to fruition without the help of AI. His response surprised me. “Honestly, no. It [Bosh] wouldn’t have happened yet. Only because my personal reality is that I simply don’t have time”, Alex said. “AI has definitely given me that window of opportunity, which I didn’t think was possible” he finished.
Alex insists that AI isn’t a total replacement for programming knowledge. He explained that he was able to use AI so effectively because he understood enough of the output to determine when it was giving a right or wrong answer. He cautioned that you couldn’t simply trust everything the tools suggested.
What’s Next for Bosh?
Bosh 2.0 is already in the works, and Alex is focusing on one of the most requested features from his users: recurring tasks. “Bosh works great for tasks, but not if they need to occur more than once,” Alex explained. “That’s the primary focus.” Beyond that, Alex has plenty more apps on the horizon, including a game. “The apps that will follow will be a bit more complex, and be a bit more feature-rich” he said.
Final Thoughts – Advice for Other Indie Creators
Talking to Alex reinforced something I’ve always believed — indie development isn’t just about code. It’s about vision, persistence, and finding creative ways to bring ideas to life. Bosh is a perfect example of that philosophy in action. It’s a beautifully crafted app that challenges the traditional to-do list model, designed by someone who refused to let a lack of coding experience stop him from building something great.
If you’re interested in getting your hands on Bosh, download it at boshapp.com. And if you want to see more of Alex’s work, visit acsoi.studio.
Each month, Kernel Extension features indie developers doing what they love most. I would love to hear your story. Send me a message and let’s talk!
Swift Snippets: Understanding @retroactive
At the end of every Kernel Extension issue we highlight a lesser-known bit of Swift. Tips and tricks that can make your dev life a little easier. Whether it’s a hidden gem in the language or a tip you didn’t know you needed, this section keeps things short, practical, and straight to the point. On that, let’s look at this issue’s Swift Snippet.
Swift’s @retroactive attribute is a great tool that allows you to extend existing types, including those you don’t own, without modifying their source. This is particularly helpful when using external frameworks, system types, or closed-source libraries.
Let’s look at the basics. @retroactive is used to add conformance of a type to a protocol retroactively, meaning after the type has already been defined. This differs from a normal extension in that it can modify a type’s behavior at a deeper level, often in ways that were previously impossible without modifying the original source.
Here’s a quick example of how you might use @Retroactive to extend an external type to conform to a protocol:
@attached(extension, conformances: CustomStringConvertible)
@retroactive
extension CLLocationCoordinate2D {
var description: String {
"(\(latitude), \(longitude))"
}
}
Here, we extend CLLocationCoordinate2D (a type from Core Location) to conform to CustomStringConvertible, allowing it to provide a custom description. Normally, extending external types with protocol conformance can lead to conflicts or unexpected behavior, but @retroactive helps mitigate these issues by explicitly marking the extension as an after-the-fact addition.
When should you use @retroactive?
• When you need to conform a type to a protocol without modifying the original definition.
• When working with external libraries where modifying source code isn’t possible.
• When defining a Swift macro that needs to apply changes to existing types cleanly.
It’s a small but impactful feature that offers more flexibility when designing Swift APIs, particularly in macro-powered code generation. You’re not going to use it in every project, but knowing when and how to apply it can save you from unnecessary boilerplate and workaround-heavy solutions.
A Peek at Next Month
As indie developers, we pour our time, energy, and resources into building something meaningful. But what does it really take to go indie? In the next issue of Kernel Extension, we’re diving into the true cost of indie development. We look at it financially, mentally, and creatively. Whether you’re considering the leap or already deep in the trenches, we’ll break down the realities of making it on your own.
If you enjoyed this, you can find more at Kernel Extension on Substack. I also share my work, thoughts on development, and the occasional indie app shoutout all over the internet. Check out kernelextension.com and find me in your favorite places.
See you in the next one,
Jack