PodSearch

Under the Radar

262: Managing Change

 

00:00:00 ◼   ► Welcome to Under the Radar, a show about independent iOS app development.

00:00:04 ◼   ► I'm Marco Arment.

00:00:05 ◼   ► And I'm David Smith. Under the Radar is usually not longer than 30 minutes, so let's get started.

00:00:09 ◼   ► So this week we wanted to talk about managing some changes that we're doing that feel risky

00:00:17 ◼   ► because they involve changing long established behaviors or UI characteristics or code even in our apps.

00:00:28 ◼   ► apps and it can be tricky. When you're first starting out making something new, you have

00:00:33 ◼   ► no users, you have no traffic, you have no data, and so you can kind of change whatever

00:00:39 ◼   ► you want all the time. I remember back in the Overcast 1.0 beta, there was so much change

00:00:46 ◼   ► during that beta period and huge changes to the way the app worked, to how it looked,

00:00:51 ◼   ► to even what the features were, how the features worked, like massive changes during that period

00:00:56 ◼   ► because there was no legacy, there was no data, the user base was like 50 people, it

00:01:02 ◼   ► was a very relatively small thing.

00:01:06 ◼   ► And so I was able to iterate quickly.

00:01:09 ◼   ► As time has gone on, I mean that was eight years ago, I have been less and less able

00:01:14 ◼   ► to make those big changes.

00:01:16 ◼   ► And there's been lots of reasons for that.

00:01:18 ◼   ► Part of it has been just my workload and my life, I've had less time to do really big

00:01:25 ◼   ► coding blocks. A bigger part is just that the app has gotten really well established.

00:01:30 ◼   ► You know, I'm very fortunate that the app has a lot of users, I manage a lot of volume

00:01:35 ◼   ► of usage and of user data, and I have, you know, if anything I change, I hit a bunch

00:01:42 ◼   ► of one-star reviews and a bunch of five-star reviews. And a bunch of people saying, "Why

00:01:47 ◼   ► don't you just make it a setting?" So anyway.

00:01:50 ◼   ► Why don't you just?

00:01:52 ◼   ► That phrase, nothing that's ever followed,

00:01:54 ◼   ► why don't you just, has ever actually been constructive,

00:01:56 ◼   ► I think.

00:01:58 ◼   ► - Any comment that begins with why don't you just

00:02:00 ◼   ► instantly says you don't understand the problem.

00:02:02 ◼   ► - Yes, it is.

00:02:03 ◼   ► Everything is more complicated than you imagine it to be.

00:02:05 ◼   ► - Exactly, exactly.

00:02:07 ◼   ► But anyways, so I've recently undertaken

00:02:09 ◼   ► a few of these changes over the last couple of weeks,

00:02:12 ◼   ► kind of unplanned, but that's kinda how I work,

00:02:14 ◼   ► and you're tackling some big ones as well.

00:02:17 ◼   ► So first, I wanna hear,

00:02:19 ◼   ► What is the large change management

00:02:22 ◼   ► that you're doing recently?

00:02:23 ◼   ► - Yeah, so in this version five update of Podometer++

00:02:27 ◼   ► that I've been working on for the last few months,

00:02:29 ◼   ► which I think, hopefully, fingers crossed,

00:02:31 ◼   ► I will be submitting early next week,

00:02:33 ◼   ► which I am thrilled by.

00:02:35 ◼   ► - Nice.

00:02:35 ◼   ► - It's essentially rebuilding the entire app

00:02:40 ◼   ► from almost the ground up,

00:02:42 ◼   ► from maybe the second floor up.

00:02:44 ◼   ► I'm leaving some old Objective-C

00:02:48 ◼   ► layer stuff, but everything else is a complete rebuild to essentially modernize the app,

00:02:54 ◼   ► to add a bunch of new features, to do a lot of big, essentially put myself in a position

00:02:58 ◼   ► to actually move the app forward rather than feeling like I'm trapped in the past, which

00:03:03 ◼   ► is how I've been feeling for a long time.

00:03:06 ◼   ► But it's like so much of this is this weird, this terrifying feeling of, so I have something

00:03:13 ◼   ► in the App Store right now that works.

00:03:15 ◼   ► It's like battle tested.

00:03:16 ◼   ► It's proven.

00:03:17 ◼   ► there for, you know, almost a decade now, in some form, and it is very stable. And I'm

00:03:23 ◼   ► going to essentially rip it out and replace it, which I think is the right call in this

00:03:28 ◼   ► situation. Like, I think I can't maintain an Objective C UI kit app going forward into

00:03:33 ◼   ► the future. Like it is just at a certain point, I'm going to have to migrate it. And I may

00:03:37 ◼   ► as well do that now that, you know, the APIs are mature, but most people are running the

00:03:42 ◼   ► latest operating systems, all the good things that are like reasons it's a good idea. But

00:03:45 ◼   ► it's like I'm fundamentally changing the thing that is so vital to my business. And

00:03:51 ◼   ► so that change is just terrifying. I mean, I've gone through this a few times where

00:03:56 ◼   ► I've made changes like this, and I think in the back of my mind I always have that

00:04:00 ◼   ► feeling of "You don't want to kill the golden goose," like the nursery rhyme about

00:04:06 ◼   ► that, where it's that sense of there's this thing that's working, and if I make

00:04:10 ◼   ► a change, this thing could just go away. And that's really problematic that in theory, you hope that

00:04:17 ◼   ► it's just like, "Oh, you get 25-star reviews, 21-star reviews, it all balances out, and it kind

00:04:24 ◼   ► of moves forward as though nothing has changed." Or in the best case, maybe you get a different

00:04:31 ◼   ► ratio of those, that it's like 25-star reviews and five one-star reviews. Most people like it,

00:04:36 ◼   ► it, the few people don't like it, whatever. But no matter what, there's always that risk of it's like

00:04:41 ◼   ► 50 one-star reviews and no positive reviews. All the work has sort of gone poorly and terribly and

00:04:48 ◼   ► everything falls apart and your professional life is over. That's the risk that's always in the

00:04:56 ◼   ► back of my head when I'm going through these kind of big fundamental changes. And it never gets

00:05:01 ◼   ► easier. Like, I've done this many times now. I've gone through many things, and it's much

00:05:06 ◼   ► easier, I will say, back in the day when my apps had hundreds of users. It was much easier

00:05:11 ◼   ► to manage than in a situation now where I think we're both in a position where our apps

00:05:15 ◼   ► have large enough audiences that you make a change. Even if 1% of those people don't

00:05:20 ◼   ► like it, that's a lot of people. That's a number of people who could both make your life

00:05:24 ◼   ► difficult in terms of reviews in the App Store or all kinds of other places, or just in general,

00:05:30 ◼   ► Like, it's an absolute number.

00:05:31 ◼   ► It's a lot of people that might get really annoyed and disappointed.

00:05:35 ◼   ► And I don't want to disappoint anybody.

00:05:37 ◼   ► I like someone who likes my app now.

00:05:38 ◼   ► I want them to keep liking my app.

00:05:40 ◼   ► I don't want that to change.

00:05:42 ◼   ► So it's a dangerous thing to do, and so I always feel really nervous and tricky about

00:05:46 ◼   ► actually going and doing it.

00:05:48 ◼   ► Yeah, that's exactly what I've been facing, even the numbers you threw out, like the 1

00:05:53 ◼   ► percent.

00:05:54 ◼   ► So, one of the big risks that I took recently is, about a week ago, I ended support—and

00:06:04 ◼   ► I said I was going to do it on Mastodon, like I said, ahead of time, but not everybody follows

00:06:08 ◼   ► me on Mastodon, obviously.

00:06:09 ◼   ► So I ended support for some really old versions of my sync API that runs on my servers.

00:06:16 ◼   ► And this was in part—this was mostly because I'm in the middle of this giant migration

00:06:21 ◼   ► that's another huge change that I'm managing

00:06:24 ◼   ► and that I'm very stressed about.

00:06:26 ◼   ► So basically, as I've talked about many times before,

00:06:28 ◼   ► I'll be brief, because this is a brief show.

00:06:30 ◼   ► I've been doing server migrations and server tweaks

00:06:33 ◼   ► to basically scale the business better,

00:06:36 ◼   ► to lighten the server load, to make sync faster

00:06:38 ◼   ► and more reliable, and to lower my server costs,

00:06:41 ◼   ► 'cause my costs just keep going up and up

00:06:43 ◼   ► and they're getting really crazy.

00:06:45 ◼   ► So anyway, it's been very, very stressful,

00:06:48 ◼   ► but I'm actually making pretty good progress

00:06:49 ◼   ► of kind of moving everything into this new, a newly architected handful of classes and

00:06:57 ◼   ► functions in the back end, where I'm consolidating all of the access to these two massive high

00:07:02 ◼   ► traffic tables, the subscriptions and the episode progress tables basically, consolidating

00:07:08 ◼   ► the access to those two tables all now through this one unified class that has the ability

00:07:14 ◼   ► to read and write that in two different ways. One of them is the new way that I'm trying

00:07:18 ◼   ► to migrate to where it's going to be way smaller, way easier to host, and give you more flexibility

00:07:23 ◼   ► in how it's hosted in the future.

00:07:25 ◼   ► Like, I could, you know, the new class has the ability to do things like instead of hosting

00:07:29 ◼   ► it on local MySQL servers, I could host it like on a managed database service, you know,

00:07:34 ◼   ► where then I don't have to deal with a lot of this stuff and scaling becomes easier,

00:07:38 ◼   ► performance becomes better, cost might be better in certain ways, I don't have to deal

00:07:41 ◼   ► with backups and replication and sync and everything else.

00:07:44 ◼   ► So moving at all towards this new system.

00:07:46 ◼   ► So this has involved rewriting and refactoring

00:07:49 ◼   ► tons of the server code.

00:07:51 ◼   ► Because it turns out, when you run a podcast app,

00:07:54 ◼   ► Sync Servers, a lot of code involves reading and writing

00:07:57 ◼   ► to the tables that deal with what podcasts you are subscribed

00:07:59 ◼   ► to, what your settings are, and what your progress and status

00:08:03 ◼   ► of every episode is.

00:08:06 ◼   ► So anyway, massive changes here.

00:08:09 ◼   ► And in the process of doing all of that, which, again, that

00:08:12 ◼   ► alone has been terrifying.

00:08:15 ◼   ► But also very, so far it's been very fulfilling

00:08:19 ◼   ► in that by doing this I've been able to make some things

00:08:21 ◼   ► more efficient already, even before I've started

00:08:23 ◼   ► using the new table structure.

00:08:25 ◼   ► I've been making a lot of things more efficient

00:08:27 ◼   ► with the old table structure and everything.

00:08:29 ◼   ► But as part of doing this, the way I've managed

00:08:33 ◼   ► my API versioning over time is I basically just copy

00:08:38 ◼   ► the controller, the API controller.

00:08:40 ◼   ► I have like API one, API two, API three.

00:08:43 ◼   ► Whenever I do a major API version change where the method by which the app syncs to the servers

00:08:48 ◼   ► has to change in a big way, I just copy, I make a new API controller, and I make the

00:08:53 ◼   ► whole protocol in that, and then I just have the old one around, just running untouched.

00:08:59 ◼   ► Now as I'm making all these changes to the low-level data storage and how it's accessed

00:09:05 ◼   ► and everything else, these are pretty large changes to the code, and so I had to make

00:09:11 ◼   ► a difficult choice.

00:09:12 ◼   ► either just keep the most modern API files up to date and refactor those to use the new

00:09:20 ◼   ► code, or go back and refactor all of the old ones also. And I chose not to do that for

00:09:27 ◼   ► a few reasons. The biggest of which is that the old ones are all... the ones I was hoping

00:09:35 ◼   ► to not have to update were the ones that serve versions of iOS that the app hasn't worked

00:09:41 ◼   ► on in about a year or more.

00:09:44 ◼   ► And so this is basically everything before iOS 15.

00:09:47 ◼   ► And when I looked at my usage, it actually is,

00:09:50 ◼   ► it's not nothing, it's about 1%.

00:09:54 ◼   ► It's kind of funny actually.

00:09:55 ◼   ► I have about 0.7% on iOS 14,

00:09:59 ◼   ► about 0.3% on iOS 12,

00:10:03 ◼   ► and almost nobody on iOS 13.

00:10:06 ◼   ► I have almost as many people on iOS 17 as I do on iOS 13.

00:10:11 ◼   ► iOS 17 is in doubt yet.

00:10:12 ◼   ► (laughs)

00:10:14 ◼   ► So, iOS 13, yes, it was a disaster.

00:10:18 ◼   ► Apparently everyone else thought so as well.

00:10:20 ◼   ► So it seems like the people who are holding onto iOS 14,

00:10:25 ◼   ► 'cause 15 and 14 run on the same devices,

00:10:27 ◼   ► I think from what I've gathered is mostly jailbreaks,

00:10:30 ◼   ► 'cause jailbreaks I think are still on iOS 14 only.

00:10:33 ◼   ► I don't really follow that world,

00:10:34 ◼   ► but that's what I've been told.

00:10:35 ◼   ► And also people who are just like,

00:10:39 ◼   ► who are just kind of scared to update

00:10:40 ◼   ► because they have maybe an older device

00:10:42 ◼   ► and they don't want their device to slow down.

00:10:43 ◼   ► And they've had bad experiences in the past with that.

00:10:45 ◼   ► And so like, well, you know, I have,

00:10:47 ◼   ► like, you know, somebody wrote me the day with an iPhone 11.

00:10:49 ◼   ► And that, they considered too old to run iOS 15.

00:10:52 ◼   ► They were holding it to 14.

00:10:54 ◼   ► You know, that's what happens.

00:10:56 ◼   ► Your user base, people develop these habits

00:10:58 ◼   ► with bad experiences in the past

00:10:59 ◼   ► and they refuse to update anyway.

00:11:01 ◼   ► And iOS 12 makes some sense because the devices

00:11:04 ◼   ► that are on 12 can't go past that.

00:11:05 ◼   ► like they are not compatible with 13, 14, and 15.

00:11:08 ◼   ► But all in total, this total is about 1% of my user base.

00:11:11 ◼   ► And I made the decision to actually cut that off,

00:11:16 ◼   ► because it was so much work on the server side.

00:11:20 ◼   ► Basically, my workload during this migration

00:11:22 ◼   ► would have approximately tripled.

00:11:25 ◼   ► And furthermore, I no longer maintain old devices

00:11:29 ◼   ► that can test those old API versions.

00:11:31 ◼   ► Because after a while of my app not working on an OS,

00:11:35 ◼   ► I decommissioned those test devices.

00:11:37 ◼   ► So I don't even think I have a device that's

00:11:39 ◼   ► running iOS 14 anymore.

00:11:41 ◼   ► I have an old one that can run iOS 12.

00:11:43 ◼   ► I can maybe test that, but the API that runs iOS 14,

00:11:46 ◼   ► I can't even test that myself.

00:11:48 ◼   ► And so I'm not going to rewrite this huge part of my API

00:11:51 ◼   ► file for a very small percentage of the user base

00:11:54 ◼   ► that I can't even test against.

00:11:55 ◼   ► And then I have to maintain indefinitely into the future.

00:11:57 ◼   ► So I decided-- it was a tough decision.

00:11:59 ◼   ► The last time I did this, it was probably three or four years

00:12:02 ◼   ► ago at least.

00:12:03 ◼   ► But I did cut off support.

00:12:04 ◼   ► And I've heard from those people.

00:12:06 ◼   ► Because 1% of a big number is a big number.

00:12:09 ◼   ► And so I have heard from them.

00:12:11 ◼   ► And I knew I would.

00:12:13 ◼   ► And I felt bad.

00:12:14 ◼   ► And I've tried to explain to them as nicely as I could,

00:12:16 ◼   ► here's the situation.

00:12:18 ◼   ► And for the most part, most people were like, well, OK.

00:12:21 ◼   ► Thanks anyway.

00:12:22 ◼   ► A few people were really mad, but what can you do?

00:12:25 ◼   ► And ultimately, this is what I had

00:12:27 ◼   ► to do to make the app better.

00:12:30 ◼   ► When I look at what I'm moving towards,

00:12:32 ◼   ► the world I'm moving towards by doing all these things.

00:12:35 ◼   ► Not only am I going to save server costs, which is something that I care about, but

00:12:38 ◼   ► my users don't.

00:12:40 ◼   ► But also, I'm making things less likely to break in the future, much more resilient.

00:12:46 ◼   ► But the big thing that my users will actually care about is that there have been a number

00:12:50 ◼   ► of really good features that I haven't been able to do because of the way my old sync

00:12:54 ◼   ► system worked.

00:12:55 ◼   ► And there have been a few really big annoying sync bugs that I haven't been able to fix

00:13:00 ◼   ► because of the way the old system worked.

00:13:02 ◼   ► And so, soon, once I'm on this new system,

00:13:06 ◼   ► I will be able to do some really nice features

00:13:09 ◼   ► that have been the number one requested features

00:13:11 ◼   ► for a long time.

00:13:12 ◼   ► I can finally start to do those,

00:13:14 ◼   ► because the sync system will support them.

00:13:16 ◼   ► And that's something that the old system could never do.

00:13:18 ◼   ► So, this is, I feel like, the decision you have to make

00:13:22 ◼   ► when you're managing these big changes

00:13:24 ◼   ► and taking these big risks is like,

00:13:26 ◼   ► yes, you are gonna upset some people.

00:13:28 ◼   ► That's inevitable when you change anything

00:13:30 ◼   ► that people are using. But you have to look at the bigger picture. Like, well, overall,

00:13:34 ◼   ► am I going to please more people than I upset? Is this going to allow me to get new customers

00:13:40 ◼   ► and retain my existing customers better? And unfortunately, those things often require

00:13:47 ◼   ► losing some other people. And I wish it didn't have to, but that's the reality. You can't

00:13:52 ◼   ► please everyone all the time.

00:13:54 ◼   ► Yeah. And I think there's an element of being, as long as you're being thoughtful about it,

00:13:59 ◼   ► don't just make change for change's sake and be pulling the rug out from other people

00:14:02 ◼   ► just because. It's slightly easier. But if there's a good reason, I think that is

00:14:09 ◼   ► an important thing that is very difficult to feel good about. But I think increasingly

00:14:14 ◼   ► I'm in that mindset of understanding that those small single-digit percentage numbers

00:14:21 ◼   ► of users, trying to cater to them is just going to ultimately make the product worse

00:14:29 ◼   ► and is going to make the experience of the 98% of other people have a worse experience,

00:14:35 ◼   ► rather than, you know, and that is way more important. That is such a disproportionately

00:14:41 ◼   ► valuable thing. And there's no strategy that you can take that is going to eliminate issues

00:14:45 ◼   ► with that kind of very long tail situation.

00:14:50 ◼   ► I ran into this recently, this one,

00:14:54 ◼   ► the stat just blew my mind where I was doing

00:14:55 ◼   ► the dark sky APIs going away,

00:14:58 ◼   ► and so I was doing some work with migrating away from it.

00:15:00 ◼   ► And my dark sky API calls were higher

00:15:04 ◼   ► after working through the migration stuff

00:15:07 ◼   ► than I expected them to be.

00:15:10 ◼   ► And I eventually worked this out,

00:15:11 ◼   ► that there was a bug in the very first version

00:15:11 ◼   ► version of Widgetsmith, the very first one on day one that was making way more Dark Sky

00:15:17 ◼   ► calls than it actually should and was happening for everybody, whether or not you had a membership.

00:15:22 ◼   ► So there's still 1% of my user base running that very first version of the app. And it's

00:15:27 ◼   ► like they've never updated the app in two and a half years. And okay, weather for them

00:15:33 ◼   ► is just going to stop working at some point because Dark Sky is going to go away. And

00:15:36 ◼   ► It was just one of those thoughts of like, "Yeah, those people, I can't help them.

00:15:42 ◼   ► There's nothing that I can do to that person who is in a situation where two and a half

00:15:46 ◼   ► years later, they downloaded one version of the app and they have never updated it since.

00:15:51 ◼   ► That's a choice they're making or a situation they're in, whatever the reason for that.

00:15:57 ◼   ► That is not where I should put my effort.

00:15:58 ◼   ► I should put my effort into the 98% of people who are running a version that I released

00:16:03 ◼   ► in the last six months.

00:16:05 ◼   ► That is a group, a cohort that I can work for,

00:16:09 ◼   ► make their life better, make my life better,

00:16:13 ◼   ► and put effort into in a way that is actually useful.

00:16:17 ◼   ► - We are brought to you this episode by Indeed.

00:16:19 ◼   ► When it comes to hiring, you need to trust your gut,

00:16:21 ◼   ► but what if you could give your gut some help?

00:16:24 ◼   ► When you want to find the top talent fast, you need Indeed.

00:16:27 ◼   ► Indeed is the hiring platform.

00:16:29 ◼   ► You can attract, interview, and hire all in one place.

00:16:33 ◼   ► Don't spend hours on multiple job sites

00:16:35 ◼   ► looking for candidates with the right skills

00:16:36 ◼   ► when you can do it all with Indeed.

00:16:38 ◼   ► Find top talent fast with Indeed's suite

00:16:40 ◼   ► of powerful hiring tools like Indeed Instant Match,

00:16:43 ◼   ► Assessments, and Virtual Interviews.

00:16:45 ◼   ► And if you hate waiting, Indeed's US data

00:16:47 ◼   ► shows over 80% of Indeed employers find quality candidates

00:16:51 ◼   ► whose resume on Indeed matches their job description

00:16:53 ◼   ► the moment they sponsor a job.

00:16:55 ◼   ► Instant Match really is incredible.

00:16:57 ◼   ► As soon as you sponsor a post,

00:17:00 ◼   ► you'll get that short list of quality candidates.

00:17:02 ◼   ► You can invite them to apply right away.

00:17:04 ◼   ► Join more than 3 million businesses worldwide using Indeed to hire great talent fast.

00:17:10 ◼   ► Indeed knows that when you're doing everything for your company, you can't afford to overspend

00:17:14 ◼   ► on hiring.

00:17:15 ◼   ► Visit Indeed.com/undertheradar to start hiring now.

00:17:20 ◼   ► That's Indeed spelled I-N-D-E-E-D dot com slash undertheradar.

00:17:26 ◼   ► Indeed.com/undertheradar.

00:17:29 ◼   ► Terms and conditions apply.

00:17:30 ◼   ► Cost per application pricing not available for everyone.

00:17:33 ◼   ► to hire, you need Indeed.

00:17:35 ◼   ► Our thanks to Indeed for the support of this show

00:17:37 ◼   ► and all of Relay FM.

00:17:39 ◼   ► Yeah, so I was, you know, speaking of other changes

00:17:43 ◼   ► that you can't please everybody,

00:17:45 ◼   ► I also made a couple other changes recently in my UI.

00:17:48 ◼   ► I issued a couple of app updates,

00:17:50 ◼   ► trying to solve some long-standing problems

00:17:52 ◼   ► and trying to give people a few little new features

00:17:54 ◼   ► while I work on some bigger behind-the-scenes stuff.

00:17:56 ◼   ► You know, you mentioned you're doing

00:17:57 ◼   ► this big pedometer rewrite.

00:17:59 ◼   ► You know, you kinda started from the second floor up.

00:18:02 ◼   ► I'm trying to do the same thing with Overcast.

00:18:04 ◼   ► And this is another reason why I am doing all the sync engine

00:18:07 ◼   ► work, is that I'm modernizing the back end

00:18:12 ◼   ► and adding all this support for new features,

00:18:14 ◼   ► while at the same time rewriting the entire data layer

00:18:17 ◼   ► in Overcast very slowly as part of my grand rewrite plans

00:18:21 ◼   ► that hopefully getting everything to Swift UI

00:18:23 ◼   ► and Swift and async stuff and Blackbird and everything else.

00:18:28 ◼   ► And so I'm also rewriting the sync protocol

00:18:32 ◼   ► that this new sync layer will sync to the servers with,

00:18:36 ◼   ► trying to optimize, making things as lightweight as possible

00:18:39 ◼   ► on the client.

00:18:39 ◼   ► Because there are certain things right now,

00:18:41 ◼   ► like if you're an Overcast user and you

00:18:43 ◼   ► have a lot of podcast subscriptions,

00:18:46 ◼   ► sync is a very heavy operation for you.

00:18:48 ◼   ► Because every time it syncs, it collects

00:18:52 ◼   ► all episodes of all podcasts you're subscribed to,

00:18:54 ◼   ► and kind of sends all their e-tags to the server to say,

00:18:57 ◼   ► hey, have any of these changed?

00:18:58 ◼   ► And that's on every single sync request.

00:19:00 ◼   ► And so as your collection grows, that's a very heavy operation.

00:19:04 ◼   ► So that's one of the things I'm migrating away from,

00:19:07 ◼   ► trying to make things scale better for both

00:19:09 ◼   ► the client and the servers.

00:19:11 ◼   ► But anyway, in the meantime, while I'm

00:19:13 ◼   ► doing all that, which is going to show basically

00:19:15 ◼   ► nothing to my customers for months and months and months,

00:19:18 ◼   ► I'm trying to do small features in the app that

00:19:20 ◼   ► will kind of give people just signs that I'm still alive

00:19:24 ◼   ► and still working on this app while I do the bigger

00:19:26 ◼   ► stuff behind the scenes.

00:19:27 ◼   ► And so I added some highly requested menu options

00:19:31 ◼   ► for playlist management and stuff.

00:19:33 ◼   ► I also wanted to try to tackle some longstanding issues

00:19:38 ◼   ► that people had with both the new interface

00:19:39 ◼   ► and with the interface in general.

00:19:41 ◼   ► And by the new interface, I mean the one I launched

00:19:43 ◼   ► like two years ago.

00:19:44 ◼   ► It's been a while.

00:19:45 ◼   ► - Something like that, yeah.

00:19:46 ◼   ► - Yeah, but anyway.

00:19:47 ◼   ► So one of the issues with the new interface is that

00:19:52 ◼   ► I changed for the first time in the app's history,

00:19:55 ◼   ► I changed what was shown on the home screen,

00:19:58 ◼   ► like what podcasts are shown there.

00:20:00 ◼   ► And it used to be just a stack of like,

00:20:02 ◼   ► quote, unplayed podcasts and then everything else.

00:20:06 ◼   ► And I found as a user of the app,

00:20:08 ◼   ► it was hard to find stuff.

00:20:10 ◼   ► 'Cause I would skim past one of the sections maybe

00:20:12 ◼   ► and not realize that the podcast was in the other section,

00:20:15 ◼   ► you know, whatever.

00:20:16 ◼   ► And that was a common thing,

00:20:16 ◼   ► people complained about it all the time.

00:20:17 ◼   ► So in the quote, new interface,

00:20:20 ◼   ► I changed it to be like these tabs.

00:20:22 ◼   ► This was like, it was like unplayed, active,

00:20:25 ◼   ► and archive.

00:20:26 ◼   ► And these tabs, ever since I launched it,

00:20:30 ◼   ► I've gotten a bunch of feedback on them,

00:20:32 ◼   ► some of which likes them, most of which was like,

00:20:34 ◼   ► can I just please get a list that just has

00:20:36 ◼   ► all of the podcasts in it?

00:20:39 ◼   ► And I eventually wanted that myself, too,

00:20:41 ◼   ► because I was hitting the same problem with the new layout.

00:20:43 ◼   ► I was like, well, if I don't know

00:20:45 ◼   ► whether a podcast is unplayed or active or inactive,

00:20:49 ◼   ► I don't know which one of these tabs to look for it in.

00:20:51 ◼   ► And so I was often either using search

00:20:53 ◼   ► to get around this limitation, or I would check all three lists and that feels terrible.

00:20:58 ◼   ► And so I'm like, you know what, people want an all tab.

00:21:02 ◼   ► So I just added an all tab and I got rid of the archive tab because it confused a lot

00:21:06 ◼   ► of people and everything that was in the archive tab would now be in the all tab amongst everything

00:21:11 ◼   ► else.

00:21:12 ◼   ► So I thought, this is what people actually have been really asking for for the most part,

00:21:17 ◼   ► let me try this.

00:21:19 ◼   ► And I tested it with the beta group for a little while and everyone was fine with it

00:21:22 ◼   ► for the most part, so I was like,

00:21:23 ◼   ► "All right, that sounds good."

00:21:24 ◼   ► And then, I also, you know, the concept of unplayed

00:21:28 ◼   ► in Overcast has never made sense,

00:21:31 ◼   ► because what unplayed has always meant in Overcast

00:21:35 ◼   ► is not yet deleted, which is different from unplayed.

00:21:39 ◼   ► You could have an episode that is played,

00:21:42 ◼   ► you couldn't in 1.0, but fairly soon afterwards

00:21:46 ◼   ► in the apps life cycle, I added the ability

00:21:48 ◼   ► to have an episode that was played,

00:21:50 ◼   ► but that you didn't delete yet.

00:21:51 ◼   ► And so there were all these labels in the app said unplayed,

00:21:56 ◼   ► but then you could literally have a played episode

00:21:58 ◼   ► right below that header.

00:22:00 ◼   ► And so it made no sense.

00:22:02 ◼   ► And that's another thing I've heard about forever.

00:22:04 ◼   ► And so I decided, you know what,

00:22:05 ◼   ► let me address this issue finally too.

00:22:08 ◼   ► Now I will actually change the logic

00:22:10 ◼   ► so that played episodes won't show up

00:22:12 ◼   ► in the unplayed sections.

00:22:14 ◼   ► And I shipped that out as 2023.1.

00:22:17 ◼   ► Everyone hated it.

00:22:18 ◼   ► (laughs)

00:22:21 ◼   ► Well, if you're one of the people who didn't, I'm sorry.

00:22:23 ◼   ► But in this case, you're like a 1%er,

00:22:25 ◼   ► like the previous discussion.

00:22:26 ◼   ► So it's like everyone else hated it.

00:22:29 ◼   ► I heard from so many people, I can't find my episodes now,

00:22:32 ◼   ► where did they go, you broke the way things work.

00:22:33 ◼   ► And I realized the reality is,

00:22:37 ◼   ► oh, and also everyone said they missed the archive section.

00:22:39 ◼   ► That was fun too.

00:22:40 ◼   ► But everyone loved the new all section,

00:22:41 ◼   ► but they still missed archive, and I broke that.

00:22:43 ◼   ► So I broke these two big things for people

00:22:45 ◼   ► because they were used to it the other way.

00:22:46 ◼   ► And I realized, okay, I was correct that something needed to change.

00:22:52 ◼   ► I was hearing from people, something needs to change in these two areas.

00:22:55 ◼   ► Unplayed doesn't make sense, and I can't find where podcasts are, and I want an alt-tab.

00:23:00 ◼   ► So I fairly quickly issued a 2023.2 update that addressed those problems in two different

00:23:07 ◼   ► ways.

00:23:08 ◼   ► So I realized the unplayed thing, people actually had gotten used to the way it worked, and

00:23:13 ◼   ► I was used to the way it worked, and I couldn't find stuff after it was played either.

00:23:15 ◼   ► And so I realized that it wasn't that the behavior was wrong,

00:23:20 ◼   ► the terminology was just wrong.

00:23:22 ◼   ► So I just changed the word unplayed to current,

00:23:25 ◼   ► which there is no good single word that I can find

00:23:28 ◼   ► that describes the status of episodes.

00:23:30 ◼   ► Current is not the best,

00:23:31 ◼   ► but I couldn't think of a better one.

00:23:33 ◼   ► If I can in the future, I'll change it again.

00:23:35 ◼   ► And so I just changed everything back,

00:23:37 ◼   ► all right, it works the way,

00:23:38 ◼   ► the behavior will go back to the way it was before.

00:23:41 ◼   ► I was just changing the label

00:23:43 ◼   ► so that the label now matches the behavior

00:23:45 ◼   ► rather than changing the behavior to match the label.

00:23:48 ◼   ► And that was the right move.

00:23:50 ◼   ► Now everyone's fine, no one's mad,

00:23:51 ◼   ► well now like two people are mad

00:23:53 ◼   ► 'cause they like the change I made,

00:23:54 ◼   ► but everyone else was fine, okay.

00:23:57 ◼   ► And then with the all versus archive

00:23:59 ◼   ► versus unplayed slash current slash active,

00:24:02 ◼   ► I realized what I want,

00:24:04 ◼   ► and I think I should trust what I want

00:24:05 ◼   ► because I made this app for myself for the most part,

00:24:08 ◼   ► and so people who have come to this app

00:24:10 ◼   ► usually are people who want things

00:24:12 ◼   ► the way I want them for the most part

00:24:14 ◼   ► because otherwise they wouldn't have stuck with my app.

00:24:17 ◼   ► And what I wanted, I wanted the all list.

00:24:21 ◼   ► I also wanted an archive list.

00:24:23 ◼   ► And the old active list I never used.

00:24:25 ◼   ► So I just changed that section

00:24:27 ◼   ► to now just be current, all, and archived.

00:24:31 ◼   ► That seems to be satisfying more people on the whole.

00:24:36 ◼   ► And it's not perfect, and honestly,

00:24:38 ◼   ► once I, when I do the big Swift UI rewrite,

00:24:41 ◼   ► my plan is to actually make that customizable

00:24:43 ◼   ► so that you can have whatever sections you want there.

00:24:45 ◼   ► And I'll give you three or four or five different possibilities,

00:24:48 ◼   ► and you can slot them in wherever you want.

00:24:50 ◼   ► Because that's much, much easier to do in Swift UI

00:24:53 ◼   ► than it is in my current massive UI table view or UI collection

00:24:57 ◼   ► view hack thing.

00:25:01 ◼   ► That's very difficult for me to do now,

00:25:03 ◼   ► but that will be very easy for me to do in the future.

00:25:05 ◼   ► And so my plan is this will all become customizable,

00:25:08 ◼   ► among other things in the app.

00:25:10 ◼   ► But in the meantime, I've settled on something

00:25:12 ◼   ► that I think works better for more people in the old system.

00:25:15 ◼   ► And these were all huge risks,

00:25:17 ◼   ► that changing long-standing things in the app.

00:25:19 ◼   ► But I'm happy that I got here,

00:25:22 ◼   ► and I did have to anger some people and lose some people

00:25:25 ◼   ► and get some one-star reviews along the way,

00:25:28 ◼   ► as you do with any change,

00:25:29 ◼   ► but overall, I think this is better for more people.

00:25:32 ◼   ► - Yeah, and I think there's definitely some couple lessons

00:25:35 ◼   ► in that story you just told,

00:25:38 ◼   ► where it's that sense of, I think,

00:25:40 ◼   ► It's important to realize that changes you're making are not typically irreversible. That

00:25:49 ◼   ► if you make a change, like that fear that I was talking about at the beginning of the

00:25:52 ◼   ► episode of this overwhelming sense of dread that I'm going to just destroy everything

00:25:56 ◼   ► and it's all going to just go down in flames, it's possible, pretty unlikely. Most changes,

00:26:02 ◼   ► if it turns out you got it the wrong way around, like which side was the 1%, if you got that

00:26:09 ◼   ► It's like, you can undo it. It's fine. You can go in and undo what you change, just

00:26:14 ◼   ► roll back, whatever that's going to look like for you. Usually that's possible. So

00:26:19 ◼   ► don't be so precious with these changes and think that, "Oh no, if I do this, I can

00:26:25 ◼   ► never go back." I mean, I ran into a funny one with pedometer recently where when you

00:26:29 ◼   ► reach your goal in pedometer, there's confetti that comes down from the top of the screen.

00:26:33 ◼   ► So it's been in there for a long time. People love it.

00:26:35 ◼   ► I love it. It's delightful.

00:26:37 ◼   ► loves it. I started getting beta feedback from people who were saying that the new confetti,

00:26:41 ◼   ► which I wrote written in SwiftUI, wasn't as fun as the old confetti. And at first, the

00:26:49 ◼   ► first person who said that, it's like, "Oh, whatever." And then it's like, I started getting

00:26:51 ◼   ► many people who were in the beta who were saying this to me, and I was like, "Oh, no.

00:26:55 ◼   ► I'm not going to mess with people's confetti. I'm going to undo this change." And so now

00:26:58 ◼   ► it is just the old CA, like CA emitter view, UI kit confetti, just in a UI view representable

00:27:07 ◼   ► inside of SwiftUI. It's like, "I am not messing with that." I don't want people

00:27:10 ◼   ► to be like, "Oh, the new confetti's sad." It's like, "No, I do not want to be on

00:27:15 ◼   ► the wrong side of that change." So I just undid it. It's fine.

00:27:18 ◼   ► And I think there's a wisdom in that, of being flexible. Pushing your app forward,

00:27:23 ◼   ► making sure that you find ways to make it better, and if it turns out you pushed slightly

00:27:28 ◼   ► too far, it's like, "Ease back. Back it up, change it." Ideally, you find this

00:27:32 ◼   ► out when you're doing some kind of beta test rather than, you know, when the 99% of people

00:27:38 ◼   ► who are grumpy is 99% of a few hundred people, it's much easier to manage than if it's 99%

00:27:44 ◼   ► of the entire user base. But still, when that happens, just ease up, back up, change it,

00:27:49 ◼   ► and you'll be fine.

00:27:51 ◼   ► Yeah. Yeah. For me, to undo my unread logic change, it was literally just going into my

00:28:00 ◼   ► version control and just finding that one commit that had those changes and just undoing

00:28:05 ◼   ► it and then changing all the labels to say current instead of un-rattling it was super

00:28:08 ◼   ► easy.

00:28:09 ◼   ► You know, it's harder when you're doing a massive re-write or a huge re-design, that's

00:28:14 ◼   ► way harder to roll back and in most cases you're better off not rolling it back and

00:28:19 ◼   ► just kind of making tweaks to be more successful rather than undoing months of work.

00:28:25 ◼   ► But the fast stuff you can undo pretty quickly and it's not that big of a deal and it's

00:28:29 ◼   ► worth experimenting with.

00:28:30 ◼   ► Yeah, and I think just or moreover is just being open to that is I think the most like what that looks like technically like is

00:28:36 ◼   ► Gonna widely vary and like rolling back isn't necessarily the right thing always sometimes

00:28:40 ◼   ► It's gonna be finding a new middle ground listening to what you know sometimes when people are upset about a change

00:28:46 ◼   ► It isn't that it changed. It's that you're exposing

00:28:48 ◼   ► Some assumption they were making about the app or some workflow that you were completely oblivious to

00:28:54 ◼   ► That is now being surfaced because of a change you made and it's like listen is like step number one

00:29:00 ◼   ► and all these things.

00:29:01 ◼   ► It's like, listen, try and understand what it is,

00:29:03 ◼   ► and then make the change.

00:29:04 ◼   ► And continue to move the app better.

00:29:06 ◼   ► Don't get anchored in the past,

00:29:07 ◼   ► and instead just keep making it better,

00:29:09 ◼   ► both for yourself and for your users.

00:29:11 ◼   ► - Yeah, and don't just make everything a setting.

00:29:13 ◼   ► - Yeah, that's right.

00:29:14 ◼   ► - Thanks for listening, everybody,

00:29:15 ◼   ► and we will talk to you in two weeks.

00:29:17 ◼   ► - Bye.

00:29:18 ◼   ► [ Silence ]