Why We Went Free

If you’re reading this, try out Codea — it’s free now! And if you love it, leaving a review helps us more than you know.

Today, we did something we’ve been agonising over for years: we made Codea, our app for creative coding on iOS, free to download with In-App Purchases. It used to be a $30 paid up-front app.

Codea has been on the App Store since 2011. It’s older than my children — which feels surreal.

A screenshot of the latest version from my iPhone, showing my original purchase date. This is what we used to grandfather existing customers into the new version.

Codea has been a source of income for us for many years. That income has steadily dropped, but it continues to earn about $70 per day. This isn’t enough to support our work full-time, but it’s enough to motivate us and give everyone who worked on it a little something each month. This is the main reason we waited so long to make it free.

Introducing Codea Pro

To make Codea free, we introduced Codea Pro. This puts all of the advanced features behind a paywall and limits projects to 500 lines of code. I say “limits,” but it’s not a hard cap: if you exceed 500 lines, you get a nag screen with a little countdown that allows you to “run anyway.” We made this decision so people could still share large projects with others.

Pro features include:

  • Running projects with more than 500 lines
  • iCloud sync
  • Xcode export
  • Shader Lab
  • Air Code
  • Collection management
  • Externally referenced assets

We also moved out of the Productivity category on the App Store and into the Developer Tools category. This category didn’t exist when we originally released Codea in 2011, and it felt like a good time to move.

I’m not sure whether we made the right decision financially — we’ll have to find out over the coming weeks and months. So far, all income has dropped off. Overnight, Codea went from selling a few copies a day to getting hundreds of downloads, but not earning anything. Here’s our RevenueCat dashboard. (That one subscription you see is me, testing it out.)

Note: RevenueCat picked up our first venture into In-App Purchases, 13 years ago! These have long since been removed and rolled into the main app.

And here’s our new users chart:

Despite the drop-off in income, I hope we ultimately made the right decision — for ourselves and for our users. Users can use Codea for free for small projects, and they can now share their projects with others. And for us? We have many more people using our app. People are dropping into our Discord more, and Codea is charting in places where it didn’t before. I’m thankful that people want to use our app and like it.

So try out Codea, share a project, or just say hi on our Discord. And if you love it, please consider leaving a review

You can probably stop here unless you are interested in implementation details.

Technical Addendum for Nerds

The shiny “Get Codea Pro” button

A big part of why it was so hard to make Codea free was deciding precisely what should be free, and what should be paid. I initially wanted to lock off editing entirely, but (rightly) got pushback from the team that this would be an unreasonable limitation.

In the end, we went with subscriptions, plus a lifetime unlock.

I was never a fan of subscriptions. Many years ago, I started implementing the Working Copy business model, where each feature is associated with a particular release date. When you purchase a year of updates, you’re granted permanent access to features available up to that point, and for the coming year. Realising just how much maintenance work this would be, I stopped. Going this route would have meant spending a serious amount of time just supporting the business model instead of fixing bugs and building features. Not only that, but the App Store has trained users to expect subscriptions. Even if you put in the work to give people features in perpetuity, they often don’t realise they’re not purchasing a subscription.

Random artboards showing one possible direction for the free version
More design thoughts on converting Codea to free

After months of on-and-off wrestling with support for date-associated features, and backdating existing features, I gave up. It just wasn’t worth the time and effort to fight against the App Store, even if it would have been better for users.

It was a huge relief to delete large swathes of StoreKit 1 (and then StoreKit 2) code, remove all the “gating” logic from features, and delete our custom paywalls.

Instead we went with

RevenueCat

I had used RevenueCat for my word game, Retrogram, and I loved it. Not just the product, but the people behind it. I wanted to take my mind off coding to support a business model, and this was the way to do it.

Having a shared dashboard so the team can view sales, with Discord integrations when purchases are made, is really nice. The paywall designer is also very good. Up to this point, I’d implemented several manual paywalls in first UIKit, then SwiftUI. Deleting that code and having it all live on RevenueCat made the application codebase feel more pure — I didn’t have big chunks of my application devoted to presenting and rendering paywalls. Plus, RevenueCat are way more expert at paywall design than me; starting from their templates was confidence-boosting in a way I didn’t expect.

Feature Flags

With the purchase flow solved, I needed to consider the toggles and parameters for this new “free” version of Codea. What if 500 lines was too generous? What if I didn’t want to allow people to “run anyway” when they hit their limits? What if the build we used to grandfather existing customers into Pro features was wrong?

I needed feature flags. I wanted Remote Config, but I definitely did not want to stick Firebase in my app. It’s huge, and unless I planned to use more of it, I didn’t want that dependency.

I put out a call for help on Mastodon and Threads. Many people gave great advice, and I ultimately settled on using CloudKit.

CloudKit provides a free*not free-to-use public database for your app. Users don’t even need to be signed in to iCloud to access it. I didn’t need to run a server or rely on a third-party solution — it was a pretty ideal solution.

I ended up forking an existing CloudKit feature flag library and adding the functionality I wanted.

One gotcha I ran into: on the day of release, I was going for a run. Halfway through, I hit “release” on App Store Connect (because I was impatient). Then Unsung, who had worked with me to implement a lot of these changes, told me he was able to get Codea Pro for free — as in, he was a new user and was being grandfathered into the Pro license without owning a previous version.

It turned out I hadn’t realised that publishing a scheme in the CloudKit console only publishes the record types, not the actual values. So I spent the next twenty minutes standing by the road, furiously migrating the CloudKit development database values into the CloudKit production database using my phone.

Retrospective

In hindsight, we went down a lot of dead ends while exploring alternative business models for Codea. I had a fear of breaking something that was working for us.

I think this was a harmful way to think about things. Today, I’d rather break things and learn what happens than be stuck in decision paralysis.