Matthias: Welcome to Rust in Production, a podcast about companies who use Rust to shape
Matthias: the future of infrastructure.
Matthias: I'm your host, Matthias Endler, and today we talk to Dylan Brown from Rising
Matthias: Academies about bringing Rust to schools in Africa.
Matthias: Dylan, thanks so much for being on the show today. Please say a few words about yourself.
Dylan: Hi, Matthias. Thanks. My name is Dylan Brown. I'm a South African developer.
Dylan: I've been working primarily with C# for over 10 years.
Dylan: A lot of work in .NET, a lot of work building chatbots in particular over the
Dylan: last eight or so years, primarily in spaces like fintech.
Dylan: And then in the last two years, I suppose, I've been working more heavily with
Dylan: Rust at the organization that I'm at now.
Matthias: Which is?
Dylan: That's Rising Academies. So Rising Academies is an educational organization,
Dylan: so not a tech company first. Rising started in 2014 in Sierra Leone, which is in West Africa.
Dylan: And we spent over a decade developing and refining an approach that improves
Dylan: classroom practice and student learning.
Dylan: As I said, it's not a tech company, so most of the company is not from a tech background.
Dylan: A couple of years ago, we added more education technology or edtech.
Dylan: Into our offerings to support our mission of impacting the learning of one and
Dylan: a half million students across Africa.
Dylan: So we've been trying to take everything we've learned from having physical schools
Dylan: on the ground across West Africa through crises like Ebola, COVID,
Dylan: all of that, and to try and take that and see what we can,
Dylan: build that actually helps education all across Africa.
Dylan: So these days, we're also partnering with governments across the continent and
Dylan: building out these edtech products.
Dylan: And that's where I come in. So I'm the senior engineering manager for Rori and Tari.
Dylan: So Rori is a math chatbot, which is delivered to students in schools through WhatsApp.
Dylan: It's operating in schools across seven countries, primarily in Western East Africa.
Dylan: And then Tari is a teacher-facing chatbot, which aims to use a lot of our learnings,
Dylan: about teacher training to help with teacher professional development across
Dylan: the whole continent. So being used a lot, very widely across the continent.
Matthias: So explain to me how that part works. You said that students use it via WhatsApp,
Matthias: but what is the typical workflow?
Dylan: Sure. So Rori, we found the most success with in terms of student learning by
Dylan: having Rori deployed in schools.
Dylan: So usually classes will cycle between some phones that are shared.
Dylan: So you might have a school of 250 students and maybe 50 phones,
Dylan: and they will have maybe one session a week with Rori.
Dylan: And those sessions with Rori are focused on practicing their math skills.
Dylan: So the main key loop in Rori is students getting math questions, answering them,
Dylan: having those evaluated by our systems on our side, and returning back to the
Dylan: user, either if they've got it correct, moving on to the next one,
Dylan: giving them hints if they've got it wrong, basically helping them do that math practice, which,
Dylan: students don't typically get a lot of in a typical kind of call and response classroom.
Dylan: Where a teacher is just standing there.
Dylan: And, you know, the occasional student gets to come up and write on the blackboard the answer, right?
Dylan: So one of the key things with Rori has been that ability for students to actually
Dylan: practice their math skills.
Dylan: Anecdotally, we hear a lot from students about their growing confidence in maths
Dylan: and kind of overcoming those barriers in terms of fear of mathematics.
Dylan: So that's a lot about how the kind of key loop of Rori works and how it works in schools.
Dylan: The key other observation from Rori is that it's really about trying to get
Dylan: students to the right level.
Dylan: So once again, the difference with a classroom is you have to be teaching the
Dylan: same content to everyone in the class.
Dylan: And with Rori, because individuals are practicing themselves,
Dylan: they can be practicing at all different levels.
Dylan: So you can see a class where you have students practicing everything from grade
Dylan: two to grade nine in level of maths skills that they're practicing as well.
Dylan: So, yeah, those are the two key benefits with Rori in an African context in schools.
Dylan: It's getting students to practice that maths and actually practice the skills
Dylan: and making sure that they're practicing it at the right level.
Matthias: Now, of course, an obvious question might be, why don't you use laptops for that?
Matthias: Why phones and why a chatbot via WhatsApp?
Dylan: Yeah, I think from like a traditional ed tech that we've seen in like the Western
Dylan: world or in Europe, you might expect it to be laptops or tablets.
Dylan: But practically, when you're coming into a space where a lot of schools in Africa
Dylan: don't have computers at all or they have no real computers,
Dylan: tech devices a phone is often the easiest way to get these kind of technologies
Dylan: into these schools right and it's mechanism that's easy for kids to,
Dylan: learn to use we've seen kids who have said they've not really had any experience
Dylan: to phones being able to quite easily learn to use whatsapp right and learn to
Dylan: interact with Rori and i think also once again,
Dylan: in terms of the technology you see across africa mobile phones are by far the
Dylan: most ubiquitous form of technology and whatsapp is by far the biggest,
Dylan: chat platform so when it comes to like the teachers being familiar with whatsapp,
Dylan: and just everyone having more context for what it is it makes it a lot easier,
Dylan: for us to overcome any of those kind of barriers and those learnings in the schools as well.
Matthias: What's your Rust production story?
Dylan: So a couple of years ago, we wanted to build out a service in order to enable
Dylan: us to better scale the use of Rori in schools, right? I mentioned earlier that,
Dylan: you will have students switching phones.
Dylan: So we needed a way to store a lot of the student information off the platforms that we were using.
Dylan: And so we needed to build out effectively a student service.
Dylan: And so that's where we decided to build out a service in Rust that we call the
Dylan: user service. That's more broadly because it also stores teacher data for Tari.
Dylan: There's nothing particularly special about it. It's a relatively straightforward
Dylan: API service using axum and SQLX.
Dylan: But the key thing that it enabled for us is this ability for students to share phones.
Dylan: So in order to have 200 students at a school using Rori, we no longer have to
Dylan: have 200 phones in that school, which can be quite expensive,
Dylan: we can do that with now 50 phones or 20 phones, depending on how the scheduling works in the school.
Matthias: Someone might listen to that and think, well, you could do that with any other
Matthias: technology. You could use Python, for example, or TypeScript.
Matthias: So I think my question would be, why Rust?
Dylan: True. There is nothing special about our use case that makes it explicit for Rust.
Dylan: I think for us, when we're thinking about the choice to use Rust,
Dylan: we're thinking a lot about what is it about our context that's actually the
Dylan: most relevant thing, right? I think a phrase that comes to mind a lot for me
Dylan: is education is a long game.
Dylan: We want to be building something that is sustainable, that is going to stick
Dylan: around and be with these kids for their learning in the long run.
Dylan: And I think another thing is that at Rising, we have the rising way,
Dylan: we call it, our principles that we live by.
Dylan: And one of those is we do more than anyone thought possible with less than anyone thought possible.
Dylan: And I think the key thing for people to understand is that this speaks to the.
Dylan: To working with limited resources in Africa, right? Especially in education, unfortunately.
Dylan: And it shouldn't be like this. Obviously, we would love for there to be a lot
Dylan: more resourcing for education, but that is not entirely within our control,
Dylan: right? So what we can control is what we can do with what we have.
Dylan: And I think that's a principle broader within Rising, not just specifically
Dylan: to our choice for Rust, but it does lean us in that direction,
Dylan: right? We want to make sure we're making a long-term impact with a relatively small team.
Dylan: And importantly, we also want to make sure we're controlling costs in a reasonable way, right?
Dylan: So when it comes to compute costs for a service, for example,
Dylan: the user service, I did a calculation the other day, was about 25 times cheaper
Dylan: than a comparably active service that we have that's been built with Python and Django.
Dylan: So those costs really rack up over the long run in order to make sure that we
Dylan: can keep having more and more students using Rori.
Dylan: So I think that side of things really matters.
Dylan: And I think another thing for me that's very important is the impact of the
Dylan: work that we do on the environment as well, right? So I think Rust in terms of.
Dylan: Compute, it helps you have your cloud services cost less, but that's also because
Dylan: they're using less electricity, you're using less resources.
Dylan: And Africa is unfortunately a continent that is going to be bearing the brunt
Dylan: of a lot of the environmental change that we see as a result of climate change.
Dylan: So I think inspired by a talk from Rust Lab a couple of years ago,
Dylan: I think a big reason for us is also making sure that we are doing something,
Dylan: that is not only helping the students with their education, but also with the
Dylan: communities that they live in.
Dylan: And I think being smart about the resources that we use for what we build is
Dylan: an important aspect of that.
Matthias: What went into that cost calculation between the Django app and the Rust application?
Dylan: So that cost calculation is primarily just the hosting costs on GCP for the
Dylan: API service that I was comparing there, I think, you know, there are other costs
Dylan: that we want to be aware of, right?
Dylan: When we're building out these services, there's obviously costs in terms of
Dylan: team salaries and the time that we spend, therefore, on these services that
Dylan: we're building out, right?
Dylan: What we also want to do is make sure that we're using the time of the team efficiently, right?
Dylan: And a key to that is making sure that we can be building new features and not,
Dylan: you know, firefighting production issues.
Dylan: And I think Rust has some clear benefits for that, right?
Dylan: In terms of making us able to trust that what we ship is solid,
Dylan: as well as in terms of being solid for student experience, right?
Dylan: I mentioned earlier the scenario where you have maybe 50 phones and 250 students.
Dylan: So if one student has their Rori session once a week, if Rori is down for half
Dylan: an hour and it happens to coincide with that student's session,
Dylan: then they've missed out on a whole week of their learning, right?
Dylan: And the education calendar is already very packed.
Dylan: So missing out on a week of any kind of education can be very impactful to students.
Dylan: So we also need to make sure that it's solid in terms of stability for making
Dylan: sure that that, you know, the cost of everything for the impact it makes on
Dylan: the students' learning is also taken into consideration.
Matthias: What does Rust mean for you in an engineering leadership role?
Dylan: Yeah, I think that's one of the other things that informed my decision to push for our use of Rust.
Dylan: I think for me, as an engineering leader, in other languages like Python or
Dylan: C#, I find myself a lot of the time being like,
Dylan: kind of annoying person on the code review who's like, okay,
Dylan: what happens when we return this null at the call site, right?
Dylan: And I think Rust makes it a lot easier for me to just focus on the business
Dylan: logic, to focus on what really matters when I'm doing a code review and not
Dylan: have to worry about like, have we caught this exception everywhere that this
Dylan: function is called when we add an exception here?
Dylan: Or like, have we handled the null?
Dylan: Because I know that the compiler does those things for me.
Dylan: So I think being able to almost create those kind of,
Dylan: systems within the code itself that the compiler enforces, right,
Dylan: using the type system in particular really makes it such that my,
Dylan: technical contributions get enforced in a way that doesn't just have to be me
Dylan: on a code review, and I can focus on the more substantive things.
Matthias: If I remember correctly, your background is in C#,
Matthias: Now, if you look at it from this perspective, you come from maybe C# and
Matthias: then you transition to Rust.
Matthias: How does that change your perception of what robustness means and what were
Matthias: your experiences when using Rust from that background?
Dylan: I think for me, a lot of it was about what I didn't have to worry so much about.
Dylan: So I think I also had learned some C++ and those kind of languages in university.
Dylan: So I had some understanding of like memory management and pointers and things like this from C++.
Dylan: But primarily I found in C# a lot of the time what you're worrying about,
Dylan: is memory leaks in production or you're worrying about null references or is
Dylan: this exception being handled.
Dylan: I think a lot of the challenge sometimes with C# is it does provide you
Dylan: a lot of groundwork to build a lot of really solid applications.
Dylan: But there's a lot of those edges that you kind of have to keep in your mind
Dylan: all the time that Rust allows you to,
Dylan: basically let go of and not worry so much about because the compiler is stricter
Dylan: and enforces a lot of these things, right? The memory safety is more a function of,
Dylan: Not having to be in my working memory than having to worry too much about the
Dylan: actual impact of memory leaks, for me at least.
Matthias: And what would you say about the tooling story comparing C# and Rust?
Dylan: I think C#, there's a lot of, especially in the .NET environment,
Dylan: there's a lot of tooling that is just very much built for enterprise software out of the box, right?
Dylan: That's like really the environment that most C# devs are working in.
Dylan: And I think that's the reason C# has been as prolific as it has,
Dylan: especially in areas like fintech.
Dylan: I think Rust does make you sometimes do more of that yourself.
Dylan: But I think if you know where you're going, that can be a lot easier,
Dylan: right? So I think some of the challenges we had in C# was trying to work
Dylan: against some of these frameworks and these tooling that we were using.
Dylan: Whereas in Rust, we are having to be more explicit about those decisions ourselves.
Dylan: And so we're a lot more in control of that rather than having to,
Dylan: you know, fight against that ecosystem, so to speak.
Dylan: I think one of the challenges sometimes with the Rust tooling for somebody coming
Dylan: from another language is maybe not having all that stuff immediately obvious to you.
Dylan: So for example, you know, we had a lot of success using X tasks for things that
Dylan: would normally be like scripted things you would write Python scripts for,
Dylan: So you might think, okay, I'm moving into this language, or I can't do these
Dylan: things that I do in Python that are really easy.
Dylan: But often there are ways to do these things. And sometimes the challenge is
Dylan: just figuring that out and figuring out how to do that, because you won't find
Dylan: as many YouTube videos or podcasts about Rust as you will about Python or other languages.
Matthias: Rust has a famously steep learning curve. I would like to pick your brain on this.
Matthias: Is it really that hard for a new team to get started with Rust?
Dylan: Yeah, I think it was something that was a bit intimidating at first and has
Dylan: been a bit intimidating for some folks in the team.
Dylan: But I think what I've really come to realize is that learning Rust isn't about
Dylan: learning all the details of
Dylan: the borrow checker or learning all the details about how lifetimes work.
Dylan: At least for our case learning rust is a lot more about the mindset right that
Dylan: goes into writing rust code so i think that's something that i've learned,
Dylan: is probably the better way to approach learning rust in a way that's less scary than having to,
Dylan: learn all these hard concepts up up front more learning about why why would
Dylan: i want to write this in rust right and those are things like,
Dylan: the type system, obviously,
Dylan: that can give you a lot of safety in what it is that you're writing.
Dylan: If you are used to writing code in a way where you care about types,
Dylan: like using something like Pydantic and Python, then it becomes much easier to
Dylan: transfer that mindset into Rust, right?
Dylan: Where you don't really have a choice but to care about types most of the time.
Dylan: So I think it's those kind of mindsets that are best for somebody who's learning
Dylan: Rust, right? I would focus more on.
Dylan: I would focus more on those elements of their mindset towards programming rather
Dylan: than the specifics of this is how a borrow checker works.
Dylan: This is the difference between the stack and the heap or any of these more in-detail,
Dylan: technical facts, right?
Matthias: I don't know much about C#, but certainly that was a problem with Python
Matthias: for me is that types are optional and you can switch them off and you can forget about them.
Matthias: And has gotten a lot better in recent years. But yeah, the part about Pydantic,
Matthias: resonates with me. You have to bring additional tooling like static analysis
Matthias: tooling, linters and so on to get a fraction of the power that you can have
Matthias: with Rust. But then again, I don't want to put words into your mouth. Do you agree with that?
Dylan: Yeah, I think that for me, when I look at a Python project that doesn't have
Dylan: some of that tooling that I like, like Pydantic, for example,
Dylan: it just becomes a bit more frustrating, right?
Dylan: Like it becomes more frustrating to work with. It becomes easier to just make errors as a team, right?
Dylan: Easier to be in a situation where you're now having to firefight issues in production.
Dylan: So I think that makes a big difference to me. I think it's also a case of having those types.
Dylan: It's also a case of having the type system allows you to build code that is
Dylan: also more resilient to change right it makes refactoring easier it also makes
Dylan: it a lot clearer about how your code changes over time so,
Dylan: being able to map from one type in a previous model to a new type in another
Dylan: model is a lot more straightforward with the type system than if you're dealing
Dylan: with like stringy types or you're dealing with like json you know raw json.
Matthias: You also said that you have some c++ background,
Matthias: How much did that help you getting up to speed with Rust?
Dylan: I think the C++ background was more just about concepts like pointers and references
Dylan: not being very alien to me.
Dylan: It was kind of like, oh, right, I kind of remember this from a while ago.
Dylan: But at that point, it was like 10 years ago that I'd written any C++ code.
Dylan: So I don't know that it made a huge impact. I think it's probably easier for
Dylan: somebody who's working more actively in C++.
Dylan: But I think even when I'm looking at hiring for somebody that's going to be working with Rust,
Dylan: having had them work with C++ at some point, even if it's just in university,
Dylan: I think makes a difference because you're having to deal with some of those things.
Dylan: You're having to be more aware of memory allocation. You're more aware of pointers,
Dylan: and these slightly lower level things than you have to deal with in languages like Python or Java.
Matthias: First time I hear about the Rust mindset you need, can you elaborate on that a bit more?
Dylan: I think one big thing for folks that I was working with is...
Dylan: Helping them to also understand that you can work with the compiler.
Dylan: You're not working against it. It's not like an enemy you have to defeat.
Dylan: And I think that's also a pitfall that I see a lot of AI tooling tend towards
Dylan: is just trying to get past the compiler error, not seeing the compiler as something
Dylan: that you're co-building with.
Dylan: I think when you have that mindset about the compiler, you start to realize
Dylan: where the explicitness is actually valuable.
Dylan: So like i'm not a big fan of like underscore match arms and unwrap generally
Dylan: i mean they have their place of course and,
Dylan: there's nothing wrong with using them if you know what you're doing but i think
Dylan: a lot of the times they also become like crutch for,
Dylan: bad design so i think a lot of the times it's seeing developers who favor that
Dylan: explicitness so you have an enum that you're returning or you have an option.
Dylan: It forces that explicitness of okay but what am i going to deal with what am
Dylan: I going to do when it's a none, right?
Dylan: You don't have these like hidden null refs where maybe sometimes you return
Dylan: null and you don't actually remember to deal with it at the call site, right?
Dylan: So I think the explicitness there is also valuable.
Dylan: So if I see somebody writing some Python code or C# code,
Dylan: and they're being explicit about those actions, right?
Dylan: Making sure that they are, if they're returning null from something,
Dylan: that they're doing it for a good reason, that they're making sure that the call
Dylan: site handles it, these kind of things where explicitness really matters and Rust forces that of you.
Dylan: So if you have that mindset that you want it to be like that already,
Dylan: it makes it a lot easier to work with Rust.
Matthias: If I understand the match arms part correctly, what you mean is that if you have...
Matthias: A type with three variants, foo, bar, and bass, and bar and bass would evaluate
Matthias: to the same return value, you would still write them as separate cases. Is that correct?
Dylan: Yeah, I think so. In a lot of cases, I would prefer that because to me,
Dylan: it's about, sure, you might have foo, bar, and bass now, but you might want
Dylan: to add another variant, right?
Dylan: And if you put an underscore match arm to handle foo and bar,
Dylan: and then you add Bess instead, you're going to end up handling Bess in the same
Dylan: way as foo and bar when you actually maybe wanted to handle it more like Bess.
Dylan: So I think it's a lot about that explicitness being valuable for how code changes over time as well.
Dylan: That's the real thing that I find can be a bit of a trap with underscore match
Dylan: arms and these things that are a little bit more implicit in a way.
Matthias: Yeah, because if you add another case and you had an underscore in your match
Matthias: arm, then nothing would warn you about that new case. You might forget about it.
Dylan: Yeah, exactly.
Matthias: And also what I like about that approach is that every case is one line in your diff.
Matthias: You can clearly see when you add a new case in the diff, it's not munched together into one.
Dylan: Yeah, and I think it means when you do have an underscore match on,
Dylan: you really need to ask yourself, like, is it true that for any variants I add
Dylan: to this in the future, I also definitely am going to want them handled in this way, right?
Dylan: So it makes you have to think a lot more about that rather than just,
Dylan: you know, getting the compiler to stop complaining because you've missed some variant in your match.
Matthias: Any other recommendations for more robust Rust?
Dylan: I think one of the things I've found working with Rust is making use of the new type.
Dylan: So not carrying around types that are just like I16s or strings,
Dylan: even where they could just be.
Dylan: Having new type wrappers around them makes it a lot easier when making changes
Dylan: to the code to not make errors.
Dylan: It helps you reduce the kind of engineering side errors that are a result of
Dylan: maybe mixing up two strings, like a first name and a surname, right?
Dylan: And you have these logical errors that you're not really letting the compiler help you in catching.
Dylan: So I think new type wrappers around these types, sometimes they can feel a bit painful.
Dylan: We now have to name a whole bunch more types, and everyone loves naming.
Dylan: But I think that it can really help with the long-term stability as well as
Dylan: avoiding some of these logical bugs that can be quite easy to make quite easy errors.
Matthias: So, for example, instead of using a number like a U32, you could use a phone
Matthias: number type, for example.
Dylan: Yeah, I think it's a good way to be explicit also about the way that you expect
Dylan: the types to be used going forward, right?
Dylan: It's like a form of documentation for the next developer to come along,
Dylan: even if that's only you in six months' time.
Matthias: Correct. Also helps you with narrowing down the type, which is a thing that
Matthias: many people often forget.
Matthias: A string is a very wide type with many valid inputs, whereas a message might not be.
Matthias: Where does validation belong?
Dylan: Yeah, I think that's a good point.
Dylan: It does also make it easier to move validation into your types, right?
Dylan: One thing that I've really liked is in other languages like C# or a typical,
Dylan: domain-driven design approach, you might have some models and you need to validate
Dylan: them at the different layers in your domain, right?
Dylan: But in Rust, you can kind of attach the validation a lot more to the actual types themselves.
Dylan: And then because of the assurances you get from type safety,
Dylan: you can be a lot more confident that when you're using the type at any point
Dylan: in your domain, that it has valid values, right?
Dylan: You don't have to recheck these things more frequently. So that's something
Dylan: I've found that's a bit different compared to other languages where you might
Dylan: have a view model and a repo model, etc.
Dylan: You know, different models for each level of your domain. In Rust,
Dylan: sometimes there is benefit to,
Dylan: using the model as much as possible across your domain because you keep that
Dylan: same validation, the same logic that ensured you constructed a valid type in the first place.
Matthias: You parsed it once and you don't have to validate it over and over again.
Dylan: Yeah, it creates that trust that you want as a developer, right?
Dylan: It allows you to not have to think about, oh, is this value valid here within my type?
Matthias: And when you built out a user service, how much did the compiler influence your architecture?
Dylan: I think that building out the user service,
Dylan: It was also a really good first project for us in Rust.
Dylan: It's taught me a lot that has made it easier, I think, to try and write more,
Dylan: idiomatic Rust, or at least idiomatic in my opinion,
Dylan: after the work we've done there.
Dylan: I think having a project that is quite similar to something you might experience
Dylan: in a lot of other languages, this API that stores user information,
Dylan: is really a good way to learn.
Dylan: So I think that it's been very beneficial there. And I think a lot of these
Dylan: lessons about the new types, you know, not fighting against the compiler,
Dylan: I think a lot of this has come from our experience of working with Rust in the user service.
Matthias: What came before the Rust user service? Was there a service in production that did the thing?
Matthias: Before Rust?
Dylan: No, not exactly. We have a platform that we use and still use for other parts
Dylan: of the stack where a lot of the student data was effectively associated to the
Dylan: phone number that they were using on WhatsApp.
Dylan: And so that meant there was sort of a tight coupling between phone and student.
Dylan: And it also meant that when, let's say, a lesson is starting,
Dylan: it's not that, you know, Dylan can just grab any phone and go with Rori.
Dylan: It means Dylan's got to get Dylan's phone if he wants to continue from where
Dylan: Dylan was working and Matthias needs to get Matthias's phone right so I think,
Dylan: a big thing as well with the like flexibility of the phones beyond just being
Dylan: able to scale the impact is also making the implementation on the ground easier
Dylan: right and that's one thing I've really,
Dylan: enjoyed working at Rising is seeing a lot more of that actually what's going
Dylan: on on the ground and being more aware of that because we have because we have
Dylan: the benefit of being able to visit our schools, speak to people who are
Dylan: working in these schools, working with the teachers, doing the implementations
Dylan: for Rori and a lot of the other projects that Rising works with.
Matthias: Are there other things you've learned before that you've brought to Rust?
Dylan: Yeah, I think one of the things that I learned in the first job that I was working
Dylan: in, where we were building an API platform for public transport data,
Dylan: was around API testing and building really solid APIs.
Dylan: And I think that also helped me a lot with the work that we were doing on the user service.
Dylan: I think one of the things we did there was we used Postman a lot for writing
Dylan: the kind of like end-to-end integration tests.
Dylan: And thankfully, since then, I found the project called Bruno,
Dylan: which is a kind of open source version of a lot of what Postman are doing.
Dylan: And it allows us to write really nice tests in a very readable format for end-to-end testing of the API.
Dylan: So I think that's been really nice for integrating into CI.
Dylan: As well as sometimes even just using with like these AI coding tools,
Dylan: because quite frankly, a lot of it does end up being a bit of like copy paste
Dylan: some boilerplate stuff to go make this Bruno test, you know,
Dylan: call the API, but with some different details for the user, right?
Dylan: When you're wanting to create them.
Dylan: And so I think those Bruno tests have been really nice to help us with confirming
Dylan: things work in the way that we want from an end to end side.
Dylan: So one thing that Rust doesn't give us is if we change things about the type
Dylan: that, let's say, causes the API response to change, Rust is not really going
Dylan: to tell us that the API response has changed.
Dylan: But the way that our stack works is that the service that interacts with the
Dylan: user service is a lot more dependent on the JSON structures not changing.
Dylan: So Bruno gives us a way to confirm that the JSON responses and requests conform
Dylan: to what is expected it gives us that extra safety on top of all the safety we
Dylan: have from within the Rust ecosystem.
Matthias: Even though the compiler is very strong it's not enough you need to have that
Matthias: additional security or maybe safety net.
Dylan: I like that approach.
Matthias: And let's talk about the wider context. How is the user service integrated into
Matthias: the entire flow? Do you talk directly to it from WhatsApp? Is there anything in between?
Dylan: So Rori was first built with the Turn.io platform.
Dylan: So at the moment, that's handling a lot of our conversational logic.
Dylan: And it's kind of the hub of the whole system, right?
Dylan: So from that platform, we call various different services. So we have CMS that
Dylan: stores a lot of the content that students work their way through, right?
Dylan: We have an answers API that can help with classification of if a student's answer
Dylan: is correct or incorrect, obviously very important for their practice.
Dylan: And then we have the user service, which has grown from what we first built
Dylan: it for, which was helping to identify students.
Dylan: And I think one of the interesting things about identifying students is you
Dylan: can't really just use like a username password, especially over something like WhatsApp, right?
Dylan: And there's also kids, kids don't, aren't going to remember a password.
Dylan: And nobody wants to deal with having to reset the passwords for 20 kids every
Dylan: time. And if you don't do it fast enough, well, they've lost out on their whole Rori session.
Dylan: So we had to build a way to identify them based on things that they will remember
Dylan: about themselves, right?
Dylan: So once again, having teams that could go,
Dylan: into the field, speak to kids, do some research and figure out what it is that
Dylan: we want to ask them about themselves that they can use to identify themselves
Dylan: in their subsequent sessions was also really important.
Dylan: So students can identify themselves with their first name, surname and a bunch
Dylan: of other information that they usually know about themselves, right?
Dylan: So the user service helps us match the students because their answers are usually
Dylan: not always the same exactly over time.
Dylan: And then it helps us track their activity, what they're doing within the content that I referred to,
Dylan: to enable us to both resume where they were before, as well as to help us do
Dylan: analytics on both our content and Rori's approach generally to see how students
Dylan: are progressing over time.
Dylan: Which is also a very important thing for us, as a lot of our work also involves
Dylan: putting out research about the work that we're doing and what actual impact
Dylan: we're making on the student's education.
Matthias: What was your experience deploying the user service to production?
Dylan: I think for most part, the user
Dylan: service deployment and running it in production has been pretty smooth.
Dylan: We haven't really encountered any major crashes.
Dylan: The service has always been very performant, both in terms of cost and latency for responses.
Dylan: But I think one of the challenges we had is that we were not being permissive
Dylan: enough with the barrier between other services and Rust, right?
Dylan: So going back to the validation and the types, we were being a bit too strict in our validation.
Dylan: And if something goes wrong on the client side for the API, then you might reject
Dylan: something from the server side, which you don't actually want to reject.
Dylan: Because if, in our case, if students are doing activity, we kind of want to
Dylan: always store that, right?
Dylan: So we were missing some activity because we were being a bit too strict with our validation.
Dylan: It was useful in a sense that it helped us find the bug on the client side and,
Dylan: things like Sentry logs shouting at us for 400s was very useful.
Dylan: And you might think, well, you don't really need to log 400s on the server side.
Dylan: But the challenge we had is we couldn't really log those on the client side.
Dylan: So we had to do a little bit of finagling with our Sentry implementation to
Dylan: get it to let us know about those things. So that was useful.
Dylan: But it was also kind of a challenge. And it's where you have to think a little
Dylan: bit more about how the strictness of the Rust side integrates with the wider tech stack as well.
Dylan: So I think that even though you can be confident about the safeties and guarantees
Dylan: that Rust provides you, a lot of the most difficult parts are at the boundaries.
Dylan: Whether that's interacting with the clients that are dealing with your API or
Dylan: the database structures that you have to deal with mapping between maybe the
Dylan: Rust enum types and types that you can store in the database.
Matthias: What's next for Rust at Rising?
Dylan: So we're definitely pursuing more Rust at Rising. We're building out new parts
Dylan: of the tech stack that we've wanted to improve for a while with Rust.
Dylan: And we're also considering porting over other parts of the tech stack to Rust.
Dylan: I think that going back to my earlier point, Rust has some unique benefits for
Dylan: us in the African context.
Dylan: And that's like a big part of what I would like to see, right?
Dylan: We deal with a lot of unique challenges in Africa, one of which,
Dylan: for example, is in a lot of the schools that we work with, internet connection
Dylan: can be very inconsistent.
Dylan: So one thing that's a personal dream of mine would be to be able to build something
Dylan: like Rori that can actually be completely offline, right?
Dylan: So running on a device that other devices can connect to, right?
Dylan: It's a kind of Wi-Fi, internal Wi-Fi that doesn't require internet connection.
Dylan: So I think for me, being able to build more of our tech stack in Rust,
Dylan: makes it more possible for us to pursue that at some point in the future because
Dylan: Rust is well-suited to these kind of embedded systems and to running on low-resource devices.
Matthias: Yeah, that sounds pretty clever because that's precisely where Rust shines.
Matthias: You want the stability, you want the robustness because...
Matthias: Potentially, you don't have that
Matthias: many chances to do any updates on those devices once they get deployed.
Dylan: Yeah. And I think, you know, we see Rust used in a lot of interesting and niche ways.
Dylan: A lot of folks that you've spoken to on the podcast, they've been really interesting
Dylan: to learn about how they're using Rust.
Dylan: But for me, I think there's a lot of these unique challenges that we face in
Dylan: Africa that are really well suited to using Rust and what we can actually build with Rust.
Matthias: Can you elaborate on that? Where do you see Rust in Africa?
Dylan: I think increasingly a lot of places are talking about tech sovereignty,
Dylan: both in Europe and in Africa, right?
Dylan: And I think that if we want to be hosting tech in Africa and building for an
Dylan: African context, I think Rust is really well suited to that because it doesn't
Dylan: require us to be spending as much money,
Dylan: you know, on the actual resources to run these projects, right?
Dylan: The raw compute power required is less.
Dylan: And that enables us to be better aligned with the impact on the climate,
Dylan: the impact on communities where you have these data centers that would be needed
Dylan: to run these kind of projects that are running in the cloud, as well as,
Dylan: as I mentioned, the ability for us to run more offline in places where we can
Dylan: actually provide technology where
Dylan: the infrastructure for like internet connection is not quite there yet.
Matthias: How easy would it be to recruit for rust development in Africa?
Dylan: I think at Rising, we generally favor hiring folks on the continent who have
Dylan: that context for the unique challenges in Africa.
Dylan: It isn't really the case that there's like big established communities of Rustaceans
Dylan: for us to necessarily hire from in Africa.
Dylan: There is a lot of folks doing some interesting work trying to grow those communities.
Dylan: But I think for me, it's less about hiring somebody who already has Rust experience
Dylan: and more trying to hire thinking about that mindset that I was talking about.
Dylan: So it might not be that they have experience with C++ or some of these technologies
Dylan: as well, because you're going to find a lot more Python developers, for example.
Dylan: But looking at how they go about that work, like what the mindset is that they
Dylan: have towards the code that they ship, those are really the things that I look
Dylan: out for in the hiring process.
Matthias: Seems like there's a lot of momentum. What if someone's listening right now
Matthias: and thinks, oh, I would like to help?
Dylan: I think for us, we're always looking for ways to reach our North Star goal,
Dylan: right? Of impacting the education of one and a half million students across Africa.
Dylan: One of the effective ways for us to scale our impacted rising is partnering
Dylan: with governments and philanthropic funders in order to help projects like Rori,
Dylan: and Tari reach more people, right?
Dylan: So I think we're always interested in anyone who can be involved in those kinds of things.
Dylan: Like we have a very small pilot happening in The Gambia that's just one school,
Dylan: but a really great person has been working with Rising to run and getting the
Dylan: government there really excited. So...
Dylan: Particularly to folks in Africa, you never know if you can help spread what
Dylan: we're doing and help improve the educational outcomes for kids on the continent.
Matthias: I hope that more people will rise to the occasion. We talked about Rust in Africa,
Matthias: and that's a nice segue into the traditional last question of the episode,
Matthias: which is, what's your wider message to the Rust community?
Dylan: I think for me, the key thing is that we should be expanding our vision for
Dylan: where we see Rust being used, right?
Dylan: What we're doing at Rising is not the most unique case of using Rust.
Dylan: It's not a typical systems programming use case or something like that.
Dylan: It's, you know, a relatively standard API service.
Dylan: I think what we should be doing as the Rust community is spreading the use of
Dylan: Rust by being more inclusive, by including more wider uses of Rust beyond just
Dylan: making the argument for,
Dylan: oh, this is a systems programming language and it does systems programming things really well.
Dylan: Well, actually, what it does really well can be impactful for a lot of cases,
Dylan: right? Exactly what we're talking about, the sustainability,
Dylan: not only in terms of the cost and compute and the environment,
Dylan: but also just in terms of the developer work, right?
Dylan: But I think what we need to do as a Rust community is be more inclusive about
Dylan: where we use Rust to position it as a tool for building reliable,
Dylan: sustainable, maintainable systems for years to come, right?
Dylan: Education is a long game, and
Dylan: this is a great example of where we can use Rust in a very valuable way.
Matthias: Perfect. Thanks for the interview, Dylan.
Dylan: Thanks.
Matthias: Rust in Production is a podcast by corrode. It is hosted by me,
Matthias: Matthias Endler, and produced by Simon Brüggen.
Matthias: For show notes, transcripts, and to learn more about how we can help your company
Matthias: make the most of Rust, visit corrode.dev.
Matthias: Thanks for listening to Rust in Production.