Daniel: "Hey, welcome to Waiting for Review, a show about the majestic indie developer lifestyle. Join our scintillating hosts, Dave and Daniel, and let's hear about a tiny slice of their thrilling lives. Join us while waiting for review. Hey, Dave, how's it going?" Dave: "Not too bad, thank you. How are you?" Daniel: "I'm good, I'm really happy to see you again because we haven't spoken for a while and it's just a absolute pleasure to hear you again. And actually see you again because we have the cameras on. I'm also tired AF, but eh, that's just winter for me." Dave: "We do have the cameras on. Ha ha. Yeah, that's just the morning for me. That's most mornings, but yeah, coffee has been brewed on this side of the world." Daniel: "Yeah. Fantastic. Yeah, usually when we talk, you have your bathrobe on and that is just a morning thing. And I've actually started doing that too. Like I do have an old bathrobe and it's very warm and cuddly. And the other day I was like, huh, does this actually, is this actually a good idea? And I've started like just putting on my bathrobe in the morning and it makes me look like an old man." Dave: "Yeah. Mm-hmm." Daniel: "because it's not as cool as yours, but it is really, really comfortable. And I can get my coffee before like having a shower and then like putting on fresh clothes." Dave: "It is. Yeah, yeah, absolutely. So I'll do I'll do that part of my day after our call. But I am I'm I am wearing clothes underneath the bathrobe. Don't worry, then we're not in any sort of awkward. Well, I'm sorry, mate. That's Yeah, no, this this. So I don't say bathrobe I said dressing gown, but same difference. But yeah, for benefit of people who" Daniel: "Aww. Oh, um. Yeah." Dave: "will not see me in my dressing gown on this call, because it's audio by the time you hear it, of course. Oh you get... But for the benefit of you listeners, yeah it's got this big grey sort of fluffy bit around the neck and one of the reasons I like this dressing gown is because my cat likes this dressing gown. She'll sit up." Daniel: "I just took a screenshot." Dave: "um on the fluffy part of the dressing gown and um yeah I think she thinks I'm turning more into another cat or something." Daniel: "Aww, it does look very soft and cuddly." Dave: "Yeah, not like me though. That's the other thing I've buzzed my hair down to like a number two cut all over. So." Daniel: "Hahaha You're more aerodynamic now." Dave: "Yeah, yeah, true, true. And certainly fuzzy rather than fluffy. But anyway, rather than spending the whole call describing what we look like, Mr. Daniel Bluebeard, let's talk about what we've been up to. How have things been going with telemetry debt?" Daniel: "Not fair. really good. I mean, I did have a major crisis last week, which is not so good. And I can totally tell you about this. But first, one thing that was really nice was, Dave, I've been cheating on you. I appeared on another podcast, which is launched by Charlie Chapman, who was really kind to invite us, both me and Lisa, onto his show." Dave: "Mm-hmm. Oh Oh, brilliant. Yep." Daniel: "He is a fantastic interviewer. It was really pleasant to talk to him. And yeah, we had a blast. It just came out, episode 69, should be the newest episode if you go to the launch podcast. So yeah, that was really nice. He was a genuine fan. Like he was like genuinely like, oh, you know, I use telemetry like so much. And that was just like really nice to hear. That was just like, uh-huh, uh-huh." Dave: "Mm-hmm. Nice. I will link that in the show notes when this goes out. Yeah. Oh Yep." Daniel: "And then I was like, oh yeah, I use Dark Noise a lot, his app for creating white noise basically. And yeah, it was full of love. So that was really nice." Dave: "Oh, that's lovely. Yeah. We use dark noise actually. Um, yeah, my, my eldest son uses it sometimes literally to just sort of reset and, um, and have some quiet time. That's a, yeah, definitely a very good app. And yeah, Charlie's a brilliant interviewer as well. So I'm not too unhappy you cheated on me. Podcast wise. Um, I think that's, uh, you know, if you're gonna, gonna go to another podcast, Daniel, that's a brilliant one. Very, very good." Daniel: "Fantastic. Oh, that's really nice to hear. Yeah, other than that, if you follow me on Mastodon or anywhere else, or if you use Telemetry Deck, you know part of the story already, because you kind of lived through it. But yeah, so I always want to improve the performance of the Telemetry Deck calculation servers. So I had a call with Lisa, and we were like, OK, let's just" Dave: "Yep." Daniel: "tackle this one next, like just start the process with the performance stuff because a lot of these tweaks, you do the tweak, but then you can only see whether it has any effect like a few days later when like enough people have ran their calculations. And so I can see like I have a chart that basically is like the median calculation time for each and every query that goes through telemetry deck. And so I kind of have to, if I tweak something, I kind of have to wait for the chart to move. And so I tried out various things and I tried out too much. I flew too closely to the sun. I changed, I want to say I changed configuration of the database processes, the processes that we use and for the signal data, we use Apache Druid, which is a time series database and it's written in Java, which is horrible. because you always have to tell the thing how much RAM it's allowed to use instead of just like using the RAM that is being provided by the operating system. And then, and of course, if you're doing then like two processes, like if you at one point tell it, you can use seven gigabytes of RAM or whatever. And then somewhere else you tell it, or you can use four tasks of two gigabytes of RAM each. And then there's a discrepancy and that will cause crashes and stuff like that. And I tried out various tweaks at once. And what happened was a very long process that would touch all of the data and kind of like defragment it in different ways. Started running and then ran out of memory and crashed after, I don't know, two, three days of running and yeah, that was not good because It kind of took with it our historicals, which are the servers that actually do their calculation calculations. So like you would just not see anything. And then, so I restarted them and so calculation would run again, but would throw errors every now and then. So I was like, okay, this is very stressful because like so many people like wrote to me, of course they would, they." Dave: "Yep. Yep." Daniel: "like they try to be helpful. They were like, hey, did you know that actually there's like errors if you try to run calculations or actually my charts have a huge big hole in the middle? And I'm like, yes, I know, but I, and you want to, you want to answer in a very friendly way because the service that you're providing is down, so it's annoying for these people and they took the time to very, very helpfully and very friendly message you about it." Dave: "I'm sorry. One of those was me." Daniel: "But at the same time, it was super stressful just to be working on the thing and be like, uh-huh. Now I have to try, because also rebuilding all of these things, they also take a lot of time because it's just terabytes of data that needs to be shuffled around and whatever. And so it took me no less than about a week to really get the thing running again. And like..." Dave: "Yep. count." Daniel: "I tried various other tweaks because I was like, OK, this thing is down anyway. I'm going to just throw in the other things that I wanted to try out as well. For example, the Kubernetes that we use now has a larger node size with lots and lots of RAM and dedicated SSD chips so that this guy always faster and stuff like that. And then at the end, I got it working, except there was a thorn in the data set. And..." Dave: "Hey." Daniel: "a thorn in the data set. That means that there's a specific time period. And if your query does not touch that time period, everything is fine. We'll just like answer your query, no problem. But if your query touches anywhere September 1 through September 15, 2023, then it will crash the query. And yeah. And it turns out that there was a broken data set. And so I was like, okay, the only thing I can actually modify the data in Apache Druid is by dropping it and then re-ingesting it. There's no editing the data. So I would issue a drop command for the whole month of September and be like, okay, just September is gone now. And the thorn was still there." Dave: "Mm-hmm. Yep." Daniel: "And it said, oh, still like such and such many segments to drop. And it just wouldn't do anything. I waited for a day or so and it was just wouldn't delete the file. So I was like, okay, obviously, um, there's like some really, really broken file, file in there. And so I was like, okay, I'm going to change the configuration so that all the data is on all the historicals so I can then completely delete them and rebuild them one by one. So I did that, waited for everything to. to propagate, which took, of course, another day or so. And then, OK, now I'm going to kill historicals group C, which is just a third of all the historical servers. And they're just gone and then rebuild them. So they restart. They have no data. So they're going to pull all the data back from the central server, which we call lukewarm storage, because there's hot storage, cold storage. And so this one is lukewarm. And then. And then, um, then I kind of killed group B and then wait for them to rebuild, which takes six to 12 hours for the, for the data to be transferred. And then same with group A and then like the queries were working again. And that was really, really nice. So, um, so September was still not there because like I hadn't, I hadn't re-ingested it yet, so it was a whole for the whole September, but all the queries were working. So we're like, oh, okay. Whew. Luckily. So." Dave: "Mm-hmm. Yep." Daniel: "And also September is good because by default, Telemetry Deck will show you the current month and the month before. And so September would usually not be visible for most customers. So I was kind of relaxed by that point. Nothing was crashing. There was a bit of data missing, but it was very obvious that it was kind of more or less intentional. And I knew that I had all the data and various backups." Dave: "Mm-hmm." Daniel: "both in lukewarm storage and in cold storage. So I was like, OK, I'm going to have to re-ingest the data. And I was like, OK, I'm going to re-ingest the data from the purest data source, which is cold storage, which when you send a signal to telemetry deck, it goes into the ingestion server, and that will store it in two places. It will throw it into a Kafka queue, which is just a message queue. directly in the data set, but it will also throw it into a blob storage for Microsoft Azure, which is where we're hosting, and that is basically cold storage. And those are append blocks, so they're basically files that you can modify. So it can just like write a new line to the same file. And then I create a new file for every hour of the day, basically. But it turns out, of course, you cannot copy or move these files." Dave: "Mm-hmm. Mm-hmm." Daniel: "to Apache Druid if they are append blocks. They need to be converted to file blobs. So I'm like, OK, how do I do that? Can I just take a checkmark or whatever? Because those are not going to be written to anymore, because they are months old. So it's not null. You have to copy them. It is gigabytes of data. And they were solved. The help desk." Dave: "Okay. Yes." Daniel: "software or they have to help articles were like, okay, you can just you can just use this very nice desktop program to download all the files and then re upload them. So I actually tried that and after six hours was like 1% complete and this was download I have asynchronous DSL so my download is way faster than my upload. So I was like okay this is not gonna work. So instead, I opened a console directly on in the cloud." Dave: "Yeah." Daniel: "So on, on Microsoft Azure, you can basically open up, you can go to their, I don't know what it's called, their portal and then directly open up a terminal there, which kind of runs vaguely in the cloud, but it has access to all of, all of your stuff. You're basically logged in more, more or less everywhere and you can run your command there. And so that's what I did, it was way faster. Re-ingested the thing and then now it had," Dave: "Hehehe" Daniel: "September back. Oh yeah, I, it's just in, in two parts. I was like September one, one through 10. And then that then after a day or two that was done and it was like, okay, now do 20 through 30 and then September 10 was gone. And I was like, wow, that's that there's a whole September 10 now. So I'm like, okay, I'm going to just like select September 10 and just push it back in there. And then September 8 was gone. And I'm like, come on, what is happening?" Dave: "right? Whaaaaa-" Daniel: "So I do the same thing and then September 7 was good." Dave: "Oh no." Daniel: "Um, I have now pushed that. I've like, like basically deleted that segment again, re-injested it as one month. So now it's all there, but now August 31 is gone." Dave: "What on earth is going on at this stage?" Daniel: "I don't know. So I've actually written and support email to the company that mostly develops Apache Druid. Let's see how they answer. I can't tell you that. But yeah." Dave: "Yeah. Oh wow. So how have you resolved this? We've still got a gap there. Yeah." Daniel: "I haven't I'm still waiting for the answer that is like that is as far as the saga goes so far" Dave: "Oh no, okay. I was wondering if maybe you were gonna sort of say you've found the thorn itself and you've been able to take it out." Daniel: "No, the thorn is gone. The thorn is, by rebuilding all the servers, I successfully managed to remove the thorn. So this is a problem with ingesting data. And I'm very sure this is a time zone thing or a slight overlap in how I specify time ranges. You know what I mean? Like maybe, so time ranges to dates." Dave: "Okay. Yeah." Daniel: "So maybe they are inclusive or exclusive or their whole days or the minutes are included or something like that. It's just that every time I try something like that, I have to wait a few hours until the process is finished and then I can see the results. So this is just ongoing. If you want data from August 31, I'm really sorry. You will get it soon." Dave: "Thanks for watching! Oh, well, um, I think you're right. Like, you know, the previous month is going to be one of most people are sort of seeing a lot of, I do a lot of that sort of view of my, my data. Although, as you know, I also looked through the whole year, sometimes just to sort of see how stuff's going. So I saw that I was one of the people sending you the charts with the gap in. Um, sorry for the stress. Uh," Daniel: "Mm-hmm. Thank you for that. No, no, don't be like, if everything, anything is going wrong, it's like really nice to write me an email or a message or whatever, it was just the sheer volume in that case." Dave: "Yeah, yeah, I get that. And I've experienced a bit of that in the past as well with the VJ app when I changed. Sorry." Daniel: "Yeah. And also what I can do in the future to not get that volume is I can just directly post it on all my socials. And also we have a possibility of pushing out messages to the UI for telemetry deck. So if I just do that next time, then people will know that I know and won't feel the need to message me. So I've resolved to do that more often." Dave: "Mm-hmm. Yeah. So you need a kind of general service status kind of situation where you update the something with the running status and it just pushes to, to everywhere." Daniel: "Yeah, I mean, I have infrastructure for that in place, actually. If you go to status.tenementredeck.com, that is where status messages usually are. You can see the uptime and stuff like that. So that's kind of helpful. But also the user interface, both the iPhone app, which is unsupported and the web app, which is very much supported, will ask a specific API endpoint. And so that can return a list of messages to display." Dave: "Mm-hmm. Yeah, that's, yeah, I think that's the thing, isn't it? Is to counter that overload of contacts, if you like, is to just, like you say, put the message out everywhere through every means possible. But it's hard to know when you wanna do that because..." Daniel: "Yeah. Exactly. Because I was in this weird, it was late at night, and it was like, okay, maybe this, this rebuild will fix everything. Maybe in like 10 minutes, it will just go like this will have this will be done, and it will just be fixed. So why, like, publicize now that like, there was an oopsie? You know what I mean?" Dave: "Mm-hmm. Mm-hmm. Yep. And the trouble is, is it sounds like you were 10 minutes away for a long time and that's where it gets tricky. Yeah." Daniel: "Yeah, for a week, basically. And I did post on social media every now and then, but I didn't use the broadcasting. And so in retrospect, I should have done that just because if something's not working perfectly, people should just know. And so to that end, I also kind of posted a blog post the other day, or I wrote it yesterday, but I posted it today. Just telling people like, hey, this has happened. And..." Dave: "Mm-hmm. Yeah." Daniel: "This is the reason and this is how it looks like and stuff. And it even has this nice graph where you can see that the mean query performance is actually, or the mean query length, like the length of time it takes to actually calculate a query, has actually gone down with the various changes that I did." Dave: "Yep, yep, so you've got some good news off the end of it in that sense. I don't envy you at that point at all dealing with that sort of pressure I guess that you'd have been feeling in the middle of it, but it's certainly good that you've got to this stage and I think you'll find out where August 31 has gone in due course I'm sure." Daniel: "Yeah, I will find that date. And then all will be good. And yeah, we just need a few more big customers for Telemetry Deck, and then I will just be able to afford a second Kubernetes cluster where I can try out these things without having to try it out on live." Dave: "Yeah. Fair, fair. And you know, that's part of the life at this stage, right? You're, I want to avoid saying the word startup because it doesn't feel like you're running it in sort of stereotypical startup fashion. You're something more indie than that in my mind. But yeah, you're still in this starting things up phase for some things in a sense, in terms of like the broader infrastructure you might have, like you say with... with more revenue and that is, yeah, I could see this being where you're at any year from now, for example, that you've got all the different clusters for testing and all of that." Daniel: "Yeah, totally. And I mean, like I've had, um, they had, they had, they have been like stages in building the service and basically every time something fundamentally changed, they were more or something fundamentally broke, there were more backups, more scalability, more, um, mitigations where if something falls down, then another thing kind of, kind of pick it up again. This, this kind of thing. And so even now with this very stressful phase where a significant portion of the servers didn't work properly, all the data is still there. So not only did the file-based backup completely pick up everything, because of course, also the message queue was just like, oh yeah, I'm just going to store this locally until something picks it up, like didn't break a sweat. And it would even get picked up by the still working Druid servers and then stored into their luqquan storage. So it was still fine because we did lose data at one point. And yeah, I don't want that to happen ever again. Wasn't a lot of data, but yeah, a few people were very disappointed, rightfully so." Dave: "Mm-hmm. And this is all part of the process though, as well. You know, with each successive cycle of these sort of things, you're hardening what you've got, improving what you've got, and it becomes that better product off the other side." Daniel: "Exactly. Improving the performance too. So I didn't do anything to the user interface, except I did one thing. If you use telemetry deck, you know that you have these charts. And then at the bottom of the charts, it says like when the chart has been last updated, or if it's actually updating right now, it says waiting for data. And I've changed that because I was like, why does this say waiting for data? Like this is way too passive. I can change it to calculating." Dave: "Yeah. Right." Daniel: "Because that's actually what's happening. Like, so I want to improve the performance, but if you're going to stare at a spinner, like that's been a bit of tell you that there is actually a piece of hardware that is hard at work, like dealing with your data. And that's just like hanging around waiting." Dave: "Yep. Oh that's brilliant, sometimes a little tweet like that is all you need to sort of really communicate the thing. Kind of amuses me because we are waiting for review and if I think about this episode so far Daniel I think we've definitely been waiting for data has been the context of the show. So I'm gonna just rename the podcast, rename it all." Daniel: "Yeah. I've been waiting for data a lot. Ugh." Dave: "No, but I think that might end up being the show title for this one." Daniel: "Don't, don't, I love the name. Yeah. How's your, how's GoVita doing? Like I see in the show notes, it says something about subscription pricing. And so tell me about that." Dave: "Yeah. Okay. Yeah. There's a bit of a story there. So, um, as we've talked about on the show, a couple of months back, I moved house and it was a pretty big move. Um, and also I've had a lot going on in the day job as it were. So my, my main job, um, and I've had very little time to really you know, getting into any meeting new features for Go VJ or do anything massive with it. And one of the things that I did decide to do as all this was sort of going on in my, my life around it, um, was to change the subscription pricing. So actually change how much, um, a monthly sub or a annual subscription or a lifetime up, um, unlock. Um," Daniel: "Hmm." Dave: "and just mess with the balance of those three things. So the app has a paywall, it shows, you know, the different choices with the annual subscription is kind of the one it presets on. I'll never really sell much of the annual subscription in comparison to either monthly or lifetime. One of the things I did was, like I said, just changed the pricing of these things and experiment. And so I ran this as a sort of series of like, I'll change it for this week, change it for next week. Let's see where we're at. Um, if I actually have recorded what I did, which might be relevant for people on this show. Yeah. So beforehand I had a balance of like a monthly subscription was $2.99. Annual was 17.99. So 18 bucks." Daniel: "Hahaha" Dave: "give or take. So three bucks, 18 bucks, and then lifetime was 30 bucks. And that's where it was before. And I thought, well, okay, let's give things a test. I'm going to bump lifetime up a bit more and make that maybe prohibitively expensive for some people, maybe drive them to other purchases." Daniel: "Yeah, a lifetime is hard to balance." Dave: "It is. And Govj makes like pretty much half of its revenue now is lifetime purchases every month, which is great, right? You know, subscriptions are not for everybody, and I'm more than happy to offer that route. It's just got a way against what subscription revenue brings me as well. It's got to be balanced. So I raised the roof on that. That was a 50% increase. So I did similar to annual that became 25. Yeah. Monthly became five bucks. Now that didn't work so well. I thought I saw some improvement. Then I saw a bit of a, it was just a bit average over the course of a week. I thought, okay, maybe I've kind of broken things. changed the price again, brought lifetime down to 40, annual back down to 20, monthly stayed at five. And that seemed to really tank things. I was a bit worried I'd broken something in the mix there. And so where have I settled now? Well, if I compare, I then did another price change a few days after that. So at this point, this is ran between the beginning of September." Daniel: "Huh." Dave: "and the 20th of September or so. And what I've landed on now, in comparison to what I had before, looks like this. Before Lifetime was 30 bucks, now it's 25. So I've actually reduced that by five bucks. Before Annual was 18 bucks, I've brought it down to 13. So it's more middling relative to where the top is now. But the monthly price, I've increased. from three bucks to five. So I left it there at the higher price that I've been testing. What I've now seen is that split is definitely quite pronounced. People are either buying monthly or they're buying lifetime for sure. Like annual just sort of sits in the middle and not many people are interested. But what it's meant is I am now selling more of my lifetimes because they're that bit cheaper. And..." Daniel: "Mm-hmm." Dave: "I am selling more of my monthlies at a higher price overall. So the balance feels like I've kind of dialed it in. And if I look at, so I use an app called RC kit, revenue cat kit. So you browse my revenue cat data cause it's beautiful. But if I look at say this month, In fact, let's look at it for the last 28 days. Give it a second to pull the data. What I can see there is that my revenue has increased quite a bit in the last 28 days. So the moment I'm looking at, it's clocked at just over $480 US for the app. And I think in the previous month, that was about half that. So." Daniel: "Mm-hmm." Dave: "Bear in mind that now, previous month includes some of the messing around and this, that and the other as well that I did playing with this stuff. Um, yeah, yeah. So previous period was, was two, four, nine. Um, so anyway, that's what I've done. I've done a bit of tweaking of the pricing. Um, I pushed out a bug fix for GoVJ in that time as well, but things have been pretty minimal. I've just not had the time to really get into lots and lots of dev. lately because of all those things. But yeah, messed around." Daniel: "Yeah, that's, but it's a cool, it's a cool experiment." Dave: "I think this is the thing and I guess I mentioned it on this show because a lot of Indies have got apps with subscriptions. And I think we can very easily sort of fall into the trap of, okay, it's basically working, right? You know, I'm bringing in revenue. If I look at my previous period, it's like say 249, 250 bucks. And I was reasonably happy with that overall in a sense of like, well, you know, it's a niche app. It's selling steadily at that price. Maybe that just is the market, you know? Um, and what I've since found is like, no, there's actually a whole load of people who were not happy with one of the options that I had before. Who are now happier. I think if the biggest difference here is I am selling more of these, um, lifetime unlocks, which means I won't get repeat revenue from them. Um, and if I. add it all up, you know, 25 bucks is basically five months worth of monthly. Uh, but I also know that people don't stick around on monthly forever either. So there's an element of like, am I really losing anybody? Um, you know, what I've done is basically pull through the lifetime, um, value of a monthly customer and getting it in one hit at the beginning with those lifetime people. So." Daniel: "Yeah, that's fair." Dave: "I'm definitely not any worse off provided there are people who will repeatedly be interested in the product like new customers. Um, and people are still subscribing as well. I've still got a reasonable amount of, um, rolling revenue for that. Nearly nearly half of my revenue is, is via subscriptions. So yeah, very long convoluted story short, but messing with the prices is yielded. some benefits and I'm definitely very happy with that." Daniel: "And how do you do that? Oh, sorry. I just, how do you like mess with the prices? So is this something that you edit in Revenue Cat or do you use just the App Store Connect? Or do you have a server thing somewhere? Or how does that work?" Dave: "App Store Connect, App Store Connect. So, nah, just using App Store Connect and changing stuff manually and literally just keeping a record manually in my notes app of what I changed to when on what date. So very, you know, old school, no AB testing, no automation or anything, literally just going, okay, let's see, I know, I know, but. You know, like at that point I'm like, yeah, I don't, I really have the volume coming through to necessarily do big AB testing and find a, a 1% uplift. If I do it in this way and suddenly get lots of benefit like that, it's not. There's just not that volume for an each app like this." Daniel: "Yeah, yeah. I think A-B testing makes sense once we have like maybe 500 to a thousand users hitting this, hitting that screen every month or so. And it seems like you're almost there, but maybe not quite." Dave: "Mm-hmm. Yeah, yeah. I don't know, actually. I need to check the stats on that because I do see quite a lot of impressions. So several tons of thousands of impressions a month. And then there's another percentage that goes on to install. If I look, in fact, I've got the stats here in revenue in RC kit. So I can see for the last 28 days, I've got." Daniel: "Hmm." Dave: "360 installs in that time. So yeah just under where that would make sense because the installs are people who've literally downloaded and booted the app for the first time and 600 and odd users. So again that reflects what I was saying in terms of half my revenue as well as coming from people who are subscribers like you can sort of see yeah 360 new installs. they're not the same, but you can see relative to each other, I'm carrying a subscribed base of people who are actually using the app. Yeah, beyond new folk, I guess is what I'm saying there. So yeah, anyway, that was a bit of a dive into my data. So keeping in with the waiting for data theme of the show. Yeah." Daniel: "Nice." Dave: "But I think it's probably the first time I've talked about the revenue I'm getting from GoVJ on the show. I don't necessarily go into the depths of that too far." Daniel: "do you feel about the, I mean, you kind of talked about it a little bit, but how do you feel about the lifetime unlock? Because I know that a lot of a lot of developers feel have very mixed feelings about it. Because on the one hand, you get a bunch of money upfront, which is cool. But on the other hand, you kind of give the promise for with like that you will like update and maintain that specific app for indefinitely basically, because" Dave: "Yeah. Mm-hmm." Daniel: "Regardless of how long you maintain the app, as soon as you stop, it will make people angry." Dave: "Yeah, so that's hard no matter what you do, right? I mean, if you've got a subscription-based app and you decide to sunset it, well, if you've ever offered annual subscriptions, then what, you've got a year's notice to give the last lot of people who bought your app that they won't get that year. And I mean, they can go to Apple and get a pro-routed refund as well. I mean, we saw that with Apollo and what happened with the Apollo and Reddit." Daniel: "Hmm." Dave: "One second, can you hear that buzzing? that coming through the mic for you? Brilliant that means the background noise removal is good for the surface we're using because somebody is line trimming right outside my window. I'll probably clip this from the show but uh oh geez okay." Daniel: "I cannot. No. Ha ha ha! Okay." Dave: "I've forgotten where I was. Ha ha." Daniel: "Lifetime unlocks. Hang on, I got another question and then we can go right back in. How do you actually determine the lifetime value of your customers? Is there something that Revenue Cat gives you?" Dave: "God for it. Um yeah so I've been incredibly unscientific with this and you're gonna cringe um but periodically I look through my renewals and I look at how many renewals people have had and the general sense is that I tend to see somewhere between five and six renewals on a monthly sub but this is really manual this is really I go in and check and there must be a better data way of looking at it" Daniel: "Or is it something you calculated yourself? Hmm?" Dave: "Um, with a few outliers every now and again, you know, I've just, if I look at somebody here now, they've been subscribed for, um, a year, which is fantastic. Um, so yeah, really unscientific. Um, there will be a better way of seeing it. It's probably got it in here somewhere and I've just not discovered it. Um, because there's all manner of charts and things connected." Daniel: "Mm-hmm. Yeah, but ideally, ideally the tools should just give this data to you, you know? Um, like I've actually thought the same about telemetry." Dave: "Yeah. If I look at, um, if I look. Yeah, I'm just trying to look at what I've actually been seeing. And let's have a look. So." Daniel: "Sorry." Dave: "Yeah, this is. I don't know, understand how to review this stats. I'm trying to look at realized LTV per customer. Let's look at per paying customer because that's actually the proper stat. Yeah, yeah, okay, one second. Maybe I can talk to this as I'm looking at it and seeing it. Okay, so. Hmm. No, I don't know how to interpret the stats. Excuse me. I'm looking at the last 90 days and I'm looking at where it normally sits. And this LTV per paying customer value sits at just over 12 bucks. So, yeah, maybe that's not. Not a bad step to sort of think about is that relative to that 12 bucks, my lifetime is double that. So." Daniel: "Okay, that's fair." Dave: "Yeah. And you know, with that in mind, it's a case of, well, you know, I'm making double what I might normally see from a monthly subscribed customer over the course of time, um, for a lifetime unlock. That doesn't seem like a bad trade at all for me because yeah, okay. I've lost some of my outliers who might've stayed subscribed for ages. Um, but I don't know. I guess where I want to land on this, Daniel, what I really think about this is that I feel like I have to offer it for my customer base as a whole lot of people who, um, for, for what a video mixing app does, they just want to buy the tool and they don't want the relationship. Yep. So I bought this thing. It does this boom. It's done. I don't have to keep worrying about paying for it. It is my, uh, video mixing app that I boot on my iPad." Daniel: "Mm-hmm." Dave: "you know, pretty much dedicated to this device in my, my setup or whatever. Um, and so there is that dynamic where somebody just wants to go, right. Okay. How much to just have this and move on. Um, and I feel like if I don't offer it, um, yeah, maybe I will get more subscribers, but I think they will probably move on quite quick as well. Like they'll try it for a month. Um, and then. and maybe find something else. So." Daniel: "Yeah, that does make sense." Dave: "Yeah, it's a real hard one to figure though, and I've been definitely very manual with this. And I guess for me, there is this balance that if I don't offer a lifetime upgrade, then I'm actually leaving money on the table, if that makes sense. Because I think those people won't necessarily be convinced to go with the subscription as often." Daniel: "Yeah, and I mean, I get that also from a customer perspective. There's probably like a few types of apps where I would like accept a subscription, but not all types of apps. Like for, I wanna say, my main Macedon app, Ivory. I'm like, okay, I'll be on this app every day, like for half an hour at least. So yeah, it makes sense. Okay, sure. And it's really, really nice. And it's... fits way better with my way of how I want to use social media than other apps. So yes, here, take my money. But then again, like maybe there's an app like, oh, good example, Affinity Designer, for example. I use that app once a month. If I had to pay a monthly fee for it, regardless of what it was, it would be too much because I have a very sporadic need for that application. So..." Dave: "Mm-hmm. Yep. Yes." Daniel: "I would probably look for another thing. So maybe, yeah, especially for people who are hobbyists or who maybe are VJs, but don't use your app all the time, just like as an addition to their tool set. So maybe it makes sense to be like, okay, they're going to buy this once and then just enjoy the support and the lifetime upgrades that you graciously bestow upon them." Dave: "There's another side to this Daniel as well as that I've got a user base that is regularly using it that I can see in terms of like how many people have got subscribed. I've got a user base beyond that I see in my stats that are the people who are lifetime unlocked and then there's a whole lot of people who are on the free version who are just giving it a go and seeing how they get on and finding their use for it. None of this situation stops me from selling them anything else, which is another option. So even being a subscription based app. Yeah, yeah. So I've got a few ideas for this and this is the next step. If you like. Oh, I could go over my master plan for Govj Daniel for 2024. Okay. So." Daniel: "Oh, please do." Dave: "Yeah, having a look around there, the app as it is at the moment is, um, as far as VJ software goes is reasonably basic. It gets you started. And that has been the point of it is it's there for beginners. And what I'm going to do is the lifetime unlock and the entire unlock actually is going to be rebranded. So at the moment it's called, uh, go VJ pro. So upgrade to pro. Um, I'm going to rebrand, brand this to plus. And there's a reason. So if you install the regular app at the moment, it will be your own. You can, you will be unlocked if you pay me to go VJ plus. Now, so this is following Apple branding to some degree. Cause what I'm doing is I'm reserving the slot for a pro spin-off. So the app as it is, it's got two layers." Daniel: "Heh." Dave: "Yeah, yeah, yeah. So pro basically will mean that it becomes a multi-layered video VJ software that will be orientated around the iPad and the Mac rather than the iPhone. So that will be yeah." Daniel: "I like that." Dave: "Um, yeah, and so that will leave another slot open that will let me create another app that has all these extra sort of features. And then, um, I can sell that other app at a higher price point is sort of the idea there as well. So the regular app is the beginners bit. There's then a pro app for all these extra features and, uh, Yeah, hopefully I can then shift some more sales of some more productive VJ software that's even better than what I've got. It's kind of the plan." Daniel: "Fantastic! Yeah, that makes a lot of sense actually." Dave: "And within that master plan is also the potential of having a spin-off. So one of the things I want to mess with is generative video, and that'll involve shaders and that sort of thing. And I'm thinking I'm going to actually run that as its own dedicated app as well, that will be kind of linked to the VJ software. Yes, yes, exactly. So with it," Daniel: "Yeah, Lego apps." Dave: "You know, if you, there'll be this, this shader orientated video software where you can set presets. You can have it respond to the audio inputs and just mess around with it on its own and should be quite fun to use. But if you also have GoVJ, they will share an app container and you'll be able to access your presets from the VJ software as well. And then use them as inputs into anything you're mixing. So." Daniel: "Very good. Have you considered different name schemes for the different Go VJ products? Like the phone version could be Go VJ, the iPad version could be Go VJ Max, and then the version that you run on your Apple watch could be Go VJ Tiny." Dave: "Mm-hmm. Hehehehehehe I mean maybe, Apple Watch maybe not. Well, I'll never say never. There's a possibility of like some sort of other UI there, but I think it would be Apple Watch in combination with the Vision Pro providing the rest of the UI or something. I don't know. Yeah, I'm still not settled on the naming scheme and it kind of..." Daniel: "Hahaha. Oh yeah, of course." Dave: "depends on what I come up with for this shader app as well. They've all got to make sense as a family. But that's kind of where my headset is, to actually group these things together and build other options for power users, if you like, and have a couple of other options within these spin-off ideas, where people who don't have any concern... watching my language there, but there are plenty of people out there who want nice visual things who don't want to become VJs. Yeah. You know, I just want to put something on the screen and it's responding to the audio visualizer style and I want to make room for that sort of customer as well, because, yeah, that's actually kind of where I'm at a lot of the time. I want something doing something fun while I've just got my music playing and I'm doing other things like" Daniel: "I'm going to go get a drink." Dave: "That's also something I want to explore. So these are the master plans. We'll see how I go. You know, that, that's a, yeah. Yeah. Um, I'm certainly not kidding myself. I'll, I'll necessarily be able to just work on this software and that's, that's my only income. But like I say, I mean, the TLDR is I've messed with my pricing and I've nearly doubled my revenue in the last couple of months. So, you know, who knows?" Daniel: "Yeah, nice. The master plans. mess with your pricing folks. That's the message." Dave: "Yeah, I think that's the main message here is never just see it as a static thing. Keep checking whatever inputs and data you want to check and having a go and seeing where things end up. I think it's certainly for a small indie app that you're not relying on as your income. I think that's a very reasonable approach." Daniel: "Yeah, totally. But also like a lot of indie developers I know and myself included kind of find it very hard to ask for money because we're like, ah, but what if, like, um, like what if people don't like my app that I've put a lot of work and blood, sweat and tears into and stuff like that. But yeah, ask for money, ask for enough money so that it's worth it to continue developing. the app or the project, otherwise, yeah, otherwise people who really love your app can't give you the money that you want and or need." Dave: "Yeah, and I think the other thing I would say to that is like, you put anything out that people are using, you will also have a support burden as you were describing earlier on in the show, you know, people hitting you when stuff is wrong or hitting you up directly when they want more features and that side of things as well. And that can be really lovely, you know, it's great that people care enough to let you know, as you were sort of saying. at the start of the show as well. It's like, yeah, you were stressed, but it's, it's a good thing that people care enough to reach out like that. But it's time consuming beyond the development that you've done to sort of maintain that contact with people. So there is another side of this as well, which is you're not just paying me for the product, but you're also paying me for being available when you've got something wrong or something you want to request as well." Daniel: "Oh yeah, totally." Dave: "Uh, and I wouldn't underestimate that. Like there's a bit of me that, uh, it's with my feedback that I get for the app. Sometimes it feels like feast or famine. Right. So I've, I've had, um, I've had some kind of shitty feedback in the last month from somebody who expected the pro upgrade to do, um, a lot more than it ever said it would do, um, and, um, you know, I had to explain to that person like, okay, the pro upgrade does this, this and this and." Daniel: "Mm-hmm." Dave: "If you're not happy, you can always unsubscribe and that was tricky. But I also had somebody who then wrote to me and said, oh, thank you for including midi support in the app. I've been using it with all sorts of midi controllers. The thing I was working on earlier in the year that took me a bit to get together, this guy wrote me back and was like, I'm using it with all sorts of things. This is the controller I'm going to play with soon." Daniel: *laughs* Dave: "And he had a feature request buried in this positive feedback. That's and that's fine. That's great. Um, but it was really lovely to hear, you know? So I think for me, all of this stuff is linked. It's not just a case of pay me for doing the dev. It's pay me for being on call for these things, if you like, and, um, and to be thinking ahead and to be adding stuff to it in the way that I'm doing. And it's not all about the money. Like clearly I've been making this out for. eight years now, making substantially less than the amount that I discussed earlier in the show. So, you know, I'm doing it anyway. But when it's paying its own way for what it's doing, it's a great feeling, actually. And like, you know, I'm looking at other things and going, okay, if I maintain this level of income, then I can upgrade my Mac, you know? And again, that goes back into working on the app and all of that. Um, so it's a bit circular, but it's a good feeling to be reaching a level of revenue where it's like, okay, this is now giving me other choices with what I do around this as well. Uh, you know, like again, looking at those, those fancy midi controllers that guy was recommending and I'm like, I could legitimately buy one of those as an expense for developing the app. Yeah, that's kind of cool. Yeah. And the app is there. It's." Daniel: "Totally. And it would be kind of nerdy and cool and fun, you know." Dave: "Yeah, yeah, yeah. So like I say, it's been a couple of months of not doing very much development in the app and coming back to it now, which is cool. And coming back to it with it in a much better state of financial health just for messing around back in September. So yeah, bit of a saga, but a lot of fun." Daniel: "Nice. Do you get many feature requests? Or is that more of a rare thing?" Dave: "Probably a good one every three or four weeks to be honest and they tend to overlap so I've got a good idea of what I want to build next. Yeah. People definitely want me to add a recording feature into the app so you can record as you go. Which yeah that'll be happening, that will definitely be happening sort of in the next few months. Yeah so there's that and then this generative stuff is definitely asked for but..." Daniel: "No, not bad." Dave: "in kind of not so many words, you know, people ask for things that will respond to audio rather than saying, Dave, I want you to make shader based generators. So, you know, but" Daniel: "Yeah, I mean it's all about how they ask, right?" Dave: "Yeah, yeah, yeah. So sometimes you've got to take a step back and sort of go, what are they really asking for here? And, and, you know, the tech is just how it gets delivered and they don't care about that bit necessarily. But, uh, yeah." Daniel: "Yeah, that's pretty cool, though. I really hope you're making a node-based UI, because node-based UIs are just the very best UIs. I just love them so much. Ha ha ha." Dave: "Uh, you have no idea. That's kind of what I've been playing within the last couple of weeks behind the scenes. So, yeah, um, because obviously we've talked about, I've, I've pulled lots of things into Swift packages around my apps to sort of make it easier to stand new things up. Um, one of the things I've been working on, um, bit by bit as I've been coming out of the developer cocoon, um, that I went into for moving house." Daniel: "Nice." Dave: "Yeah, one of the things is that I've now got a stack of core image filters that I use within my apps expressed in a package. And I thought, OK, I want to make presets that are a combination of different filters together. OK, cool. I can do that in code pretty easy. And then I thought, yeah, but editing these is actually a bit of a pain adjust a parameter or you wire up the parameters of the thing you're testing to some basic UI and then you noodle with it until you've reached a balance that you're happy with. So yeah, long story short." Daniel: "You shouldn't be noodling, your UI should noodle." Dave: "Exactly. So yes, I am looking at building a node-based UI at the moment. It's a list-based UI where I can just stack effects into this test app. And the way I've got it built is that I can export them as codable JSON and then in state any sort of composite set of effects together from that. But it's going to become a node-based UI. So yes, whether that's just for me will remain to be seen." Daniel: "Fantastic." Dave: "I might knock it together into a test flight and see if anybody else finds it fun. But yes, definitely going to build a no base thing. Yeah." Daniel: "I bet they would. And I mean, not best things are cool. And I'm pretty sure that SwiftUI would be pretty good to write such a thing. If, if there isn't even a package already for it." Dave: "I'll have to have a bit of a look. But I'm trying desperately not to give myself more work to do. So at the moment, that's the case. This is fulfilling a job of me being able to build presets and things like that for my apps. But we'll see. Maybe the DevTool becomes a shippable product inside of the next year as well. I'm sensing I've got at least one test flight user in yourself, Daniel. So." Daniel: "Very, very nice. I'm out." Dave: "Ha ha ha" Daniel: "I'm not the best VJ, but I'm just like, every time I open up Blender, which doesn't happen too much, but every time I'm just like, oh yeah, let me work with the materials and the geometry nodes and everything else that is like node-based because it's just so cool. I keep trying to cram a node-based UI into telemetry deck, but it's not really the data that I have or the data like..." Dave: "Yeah. Mm." Daniel: "the data structures that I have don't really lend themselves because they're not as freeform. Like a query has very specific properties. And so it's not just like, you can't just have a bunch of nodes for it. Same with filters and stuff like that. Like filters would probably be the most realistic one, but I actually do have a really good filter UI now. So, oh well." Dave: "Yeah. Yeah, yeah, I love what you've got there. It's got the whole sort of funnel type thing going on as well." Daniel: "Yeah, it's all very, very reusable. I'm actually in the process of wrapping all of these little elements into, uh, like UI tests, which finally, which all would already found me like four bucks. Two of which, two of which I knew about, uh, but still, um," Dave: "Awesome. Hahaha It's your own fault for testing, Daniel. You don't find the bugs if you don't test." Daniel: "Yeah. I figured I always pushed those. Like I have lots of tests on the backend, but I always felt like, yeah. Uh, like front end testing will be something that will, uh, I'll do when the, when things are a bit more stable. And I'm like, okay, either it's getting more stable now or, or never, like now's the right time to actually, uh, like be a bit less move fast and break things about UI development. And so, yeah." Dave: "Yep. Now that makes sense." Daniel: "So now I have a few tests for the individual UI components, and it's nice. All right, I have, hang on, I wrote this down. I wrote this down. I have follow up, which I can tell you in three minutes. And then, yeah. So we talked about an episode or two ago about Vision Pro, the browser, that even if I have 3D elements in my CSS, which are clearly 3D, they won't, and I wondered if it would display those in 3D space." Dave: "Go for it." Daniel: "And I checked, and it will not in any version of the SDK that I have access to, which is a bummer. It's probably also a safety measure. Either it's just like, OK, yeah, just like Safari rendering. It's rendering inside its own buffer. That's probably the technical reason. But also, even if it could do it, it probably wouldn't because I could totally put a 50 meter." Dave: "Yes." Daniel: "cube into your living room and then you wouldn't see anything except my cube and that's kind of probably not what you would want any like website to allow. So sad, but I understand." Dave: "Yeah. Well, I can imagine maybe there'll be a route there in the future." Daniel: "I still opened a feedback." Dave: "Yeah, yeah, it feels like something we might get as an extension, like some sort of formatting extension that the browser can offer in time. Yeah, but I can understand those constraints while it's sort of still in this stage. So yeah, what you said makes sense there. You don't necessarily want that sort of 3D experience just being unbidden, whatever you load suddenly pops up." Daniel: "Oh, that would be nice." Dave: "Yeah, and outside of Apple's review as well, because they are heavily curating the Vision Pros, App Store and everything else, I would imagine, as that's all coming together." Daniel: "Yeah. All right. No one at Apple told me this, what I just told you. This is just my own interpretation of why this isn't a thing. And so, yeah. Hit me up on Macedon if you wanna know the feedback number. I'm not gonna, like, I have that one in front of me and I'm not gonna read out like 12 digits on air." Dave: "to. Please don't. If you get it in the next couple of days, send it me, and I will add it to the show notes, because it takes me some time to get these edited now. Yeah. But." Daniel: "Oh yeah, I'll just add a link to the show notes. That's good, that's good. All right, if people would want to hit you up on social media about any feedbacks that you might have posted, like where would people find you? This is me introducing the outro." Dave: "Introducing the outro, OK, because yes, we do need to wrap and apologies if anybody has been able to hear the mowing that's going on outside my window here. I won't know until I play back the recording of the show if it's picked it up subtly here or there. But so I'm a little bit a little bit distracted at times by this incredibly loud noise. But getting to the point where can you find me online?" Daniel: "Huh." Dave: "You can find me at Dave at social light beam apps dot com on the mastodons and feddies. And yeah, you can find my apps at light beam apps dot com. How about yourself, Daniel?" Daniel: "Fantastic. Find me at daniel at social.telemetrydeck.com. Also find me at telemetrydeck.com. And oh yeah, if you have feature requests, my least favorite feature requests are DMs because I have to copy them into a ticket. Then it's tickets. It's just opening up a ticket directly on GitHub for the Telemetry Deck Issues repository. But my favorite way is ticket plus hey, I'm also starting to pay for a subscription. And so these are the tickets I'm working on first." Dave: "Ha ha! I think that's more than fair enough, Daniel, given the entire conversation you've just had with me. I understand. Well, I shall remember that. Thank you. Thank you very much for catching up, Daniel. It's been great to talk to you again after what feels like a little while. We keep going through these bursts. But yeah, great to catch up." Daniel: "Hint hint. All right. It's been fantastic." Dave: "So I can easy." Daniel: "All right, have a great day Dave and see you soon." Dave: "Uh, we messed it up. There we go." Daniel: "Bye! Hahaha! I was like, are you going to answer? Should I just say bye? I don't know. Who knows? It's fine." Dave: *laughs*