ALTERNATE UNIVERSE DEV

Serverless Chats

Episode #55: Serverless PHP using Bref with Matthieu Napoli

About Matthieu Napoli:

Matthieu Napoli is a software consultant and founder of null. Matthew has been developing web applications for more than 10 years with PHP and JavaScrapt as a full-stack developer, lead dev, and CTO, while maintaining several open source projects. He’s also the author of PHP-DI, Silly, Couscous, and Bref.

Watch this episode on YouTube: https://youtu.be/H8tkZcjQxOA
Transcript

Jeremy: Hi everyone. I'm Jeremy Daly, and this is Serverless Chats. Today, I'm chatting with Matthieu Napoli. Hey Matthieu. Thanks for joining me.

Matthieu: Hi, thanks for having me.

Jeremy: You are a serverless consultant and the founder of Null. Why don't you tell the listeners a little bit about your background and what Null does?

Matthieu: Yes. I created Null two years ago. My goal was to be able to both work in open source as well as work for clients. I use that company to do trainings around Bref, around serverless and also to provide consulting services.

Jeremy: What about your background?

Matthieu: I started as a developer about 10 years ago, and I've been working mostly as a developer. I've been configuring servers, setting up servers for a while. That's why I'm also really interested in serverless. I've been looking at that very closely lately.

Jeremy: Great. All right. I want to talk to you today about serverless and PHP and Bref. Serverless is obviously the topic of this podcast. We've seen quite a bit of movement in the serverless space over the course of the last five years or so. PHP sometimes gets some slack on the internet, but can you give me a brief background as to why you chose PHP?

Matthieu: Yes. That's a very good question and that's a good way to start, because indeed a lot of people have opinions about PHP, and sometimes for good reason. I started with PHP just because it was simple. That's what I love about this language. At the time, like when PHP arrived, it was about 25 years ago. The web was about creating CGI applications, using C or whatever, and PHP arrived and simplified everything. It made the web accessible to a lot of people. I find that really amazing.

That's why I started with PHP as well. I wanted to build a simple website. Yeah. I started with PHP because of that, but I'm seeing the same thing today with serverless. It's making infrastructure, it's making hosting applications accessible again to developers and I find that amazing. Yeah. I started with PHP. I kind of got stuck with this language throughout my jobs and lately PHP has become a very interesting language. To be honest, it's really interesting.

If you've used PHP in the past, I really encourage you to give it another look. It's really worth it. While I do talk a lot and use a lot of PHP, I enjoy using JavaScript as well. TypeScript lately. Really, really interesting language. Life is full of things to learn about, I guess.

Jeremy: Right. Absolutely. I agree with you on PHP. I started with PERL and CGI way, way back when, and then I think I started using PHP 3.0 or something like that with MySQL databases. You're right. It completely changed things. From that we got WordPress for better or for worse, but I think that like 80% of the web runs on PHP.

Matthieu: Yeah. That's a huge market, which is interesting when we're going to talk about AWS Lambda later. Yeah. PHP is huge and I don't think this is something that we can ignore.

Jeremy: Right. Right. Okay. Speaking of this PHP, you realized that there was a gap in the serverless ecosystem for PHP, and so you wrote something called Bref. Can you tell the listeners what that's all about?

Matthieu: Exactly. Yes. I am a developer. I like writing code, creating applications. I don't like setting up servers and all of that stuff. This is why I created Bref. I wanted a simple way to put my PHP code online. At the time I was looking into serverless, looking into AWS Lambda and I discovered, of course, that AWS Lambda does not support PHP. I created Bref to bridge the gap, run PHP on Lambda and provide a lot of tools, documentation, examples. Yeah. Anything that you may lack to create those serverless applications. I would say that Bref is more than just a runtime. It's a whole stack.

Jeremy: Right. There's actually two parts of Bref, right? Why don't you explain those two different parts?

Matthieu: Yeah. I realized over time that there are two major use cases when you look at Bref and what you can do with PHP on Lambda. In the first case, you know about AWS Lambda. You know how it works. You know why you use it. The only thing that's missing is that you want to run PHP for some reason. Maybe you want to use PHP and you want to run it on Lambda. The first part of Bref is a runtime that works just like any other language on Lambda.

Yeah. You can write functions in PHP, handle queue messages, SQS queue messages, EventBridge messages react to S3 events, API gateway events as well. You know, the usual. The second use case is different. Instead of adapting PHP to run on Lambda, there are people that know PHP and do not really know about Lambda and what they can do with it. I take it the other way around and I adapt Lambda to PHP. The approach is that users don't have to change anything in their code.

They can take their Laravel application, Symfony application or whatever, and hopefully put it in Lambda and it just works. That's a second runtime. This runtime, I mean, we can go into the details. It's really interesting because the way PHP runs is very similar to how AWS Lambda runs. Making the old PHP way run on Lambda was fairly ... I mean, I don't want to say easy, but it was doable. That's the second approach where, well, people can just start using Lambda as a web host. That's how I host Lambda as a web host instead of functions.

Jeremy: Sure. Right. The custom runtime for just the first part of it, so just being able to run PHP on Lambda, this is something that's really interesting because I know there are others that maintain PHP runtimes out there. You are optimizing it for actual PHP developers, right? You're using PHP-FPM, right?

Matthieu: Exactly. Yes. The FPM runtime, so that the FPM runtime is used for the use case where you want to use AWS Lambda as a web hosting platform. The FPM runtimes actually runs PHP-FPM, which is like PHP web server inside Lambda. Bref has a little bridge that when there is an API gateway event, will take the event, convert it into a request that PHP-FPM understands. This is the first CGI protocol and so Bref does the bridge, provides the first CGI request to PHP. Then PHP runs just as usual.

You know, the PHP execution model is you have a request, a PHP process starts, builds the whole framework, runs the request, processes the request, and returns the response and then `. I mean, this is perfect for AWS Lambda. That's why it's quite easy to integrate FPM with Lambda.

Jeremy: Right. Then you have the ability to actually create individual handlers as functions and type classes, right?

Matthieu: Exactly. Yes. This is the second part where, so the first part to me is helpful to get people started with Lambda. They start with PHP-FPM. They understand that oh Lambda is great for running a petition. Cheap. It can scale really well. Once they started with Lambda, they understand the execution model and everything. Then they can look into using those real functions like using Lambda just the way it was designed to.

With this second runtime, they write function either using standard PHP functions or using classes. Those classes, those functions are inspired by the JavaScript runtime, as well as the Java runtime for Lambda. They can write classes to process SQS events, EventBridge events, S3 or DynamoDB events and so on.

Jeremy: Yeah. That's actually really cool because I think that some of the other libraries out there just essentially have function support, right? If you're building much more complex systems that are using classes and using that kind of functionality, then the runtime that Bref provides I think is much more flexible and more interesting.

Matthieu: Yeah.

Jeremy: All right. You've got this runtime now, and you've got this ability to port PHP applications into Lambda now, but what are some of the other benefits of Bref?

Matthieu: Well, the main one I see is obviously those are the benefits of serverless. You have an application. You can drop your server that you used, where you used to run PHP, put your application in Lambda and just be done with it. You can scale. You can pay exactly for what you use. Since you already made the step of running on Lambda of configuring the little details like where do I send logs to CloudWatch? How do I store files to Amazon S3?

Once you've done all that effort, it becomes easier to write those little functions. Like I have a link, why not write it as a simple function? I want to use cues, why not send that to SQS with the adapters? Those are all those little integrations that get you started really easily. Along that, there are different libraries and tooling, like Bref provides a simple logger specifically made for AWS Lambda.

It also provides a little dashboard specifically made so that you can view the logs and a few metrics. Some tooling to run colons on Lambda. This is really common for PHP developers to be able to run Chrome tasks or MySQL migrations on their server. They need to learn to do all of that stuff on Lambda as well. Bref provides a specific tool for that.

Jeremy: Right. Yeah. That's another thing too, right? You know, because I got these confused. You think about the Bref runtime versus the Bref library itself. The Bref library itself is like this opinionated HTML framework. It gives you a lot of those capabilities, like you said, like the logger and some of that other stuff that's built in. What about local development? How do you do that?

Matthieu: Yes. That's also something that was asked very early on and it took us some time to answer the problem, but we ended up building Docker images. Those images are the same that we used to build the runtimes. This is the matches we used to compile PHP, to set the correct extensions and the correct settings and everything. We use those images to create the runtimes, and then we also provide them so that developers can run them on their machine.

That's really helpful to develop locally. It's with either the web hosting runtime and the Bref for functions runtime. For both of those runtimes, we have two different images. Yeah. For both of them, you can run this locally.

Jeremy: Nice. All right. What about publishing the application? Is there a workflow for publishing?

Matthieu: Yeah. Bref does not provide a tool for deploying. Instead, it uses the serverless framework. Early on, I started working on a YAML-based tool that would read the YAML configuration that you define and create the resources that you would need. Then I realized it exists already. You know, there's a serverless framework. There is SAM. There's CloudFormation. There's so much stuff. Yeah. Throw everything away. Bref now uses serverless and it's working really great.

Throughout the documentation we also explain how to configure serverless for PHP use cases, PHP related use cases. Websites, APIs, queue workers, those are the three main use cases. Bref also provides a serverless plugin to easily use the Bref layers, the Bref runtimes.

Jeremy: Great. All right. Let's talk about the primary use cases for a second, because I think this is really helpful for people who are thinking about building serverless applications. Like what can you do with it? Obviously PHP is built for the web. I know some people use it for ETL tasks and things like that, if you're really familiar with it. Let's say the primary use case here is serving up a website. How do you build that with Bref?

Matthieu: Right. I would say the starting point will be to use the runtime that is made with PHP-FPM, so the one that will let you use PHP just as usual. That's where you can use your favorite framework. That's great. You can work locally, create your website and then deploy with serverless. I mean, serverless.yml. You would configure your framework to send the logs to CloudWatch. That's very easy thanks to the standard outputs.

You could also configure your framework to use Amazon S3 for storage. Then you can deploy that on Lambda with API gateway as the HTTP endpoint. If you are building websites, however, and that's what we document in Bref, you can either use API gateway by itself or use CloudFront in front of API gateway. That way CloudFront can serve assets with Amazon S3 and serve the usual PHP pages through API getaway.

It's very familiar to PHP developers in my opinion, because it's like using Apache or NGINX with PHP-FPM and Apache or NGINX serving of the assets. There's not a lot of difference here. We use CloudFront and Lambda and S3, but the setup is roughly the same.

Jeremy: Right. Okay. What about if you're building APIs and like ... I get it. Let's say you're using Laravel or you're using Symfony and you get your routes in or whatever, is the only way to do this to build just the Lambda proxy integration to accept everything, or could you build separate functions for different end points?

Matthieu: Yes. I would say if you use a framework that has a router inside, so Laravel, Symfony both have routing inside of the framework. I don't think it would make sense to have different functions. It could be the monolith Lambda pattern where you have a single function, which is huge and handles all requests. You could have made it two functions. For example, if you have a front end and a backend where the front end is public and the back office is only accessible to administrators.

That could make sense to have two functions. That way you can scale functions differently. You can protect those functions differently as well. Yeah. To me, this is the main use case, the monolithic approach. Yeah.

Jeremy: Yeah. If you did want to break them up though, you just wouldn't use the framework, right?

Matthieu: Exactly. I wouldn't because then the routing will be done twice. Once you start using the API gateway routing feature, to me that's where it makes sense to write actual functions, whether with PHP classes or functions. It doesn't really matter, but write actual Lambda functions.

Jeremy: Right.

Matthieu: Bref provides ... Yeah. I didn't mention that Bref provides a small integration here where API gateway events can be automatically converted into standard PHP requests and back and the same for responses. Yeah. Just to clarify on that. PHP has a standard for requests and responses, which is called PSR-7. Bref can automatically map an event from API gateway to those objects. That's pretty good because it lets you write PHP controllers just like in any framework, but with other framework.

Jeremy: Right. Which is pretty cool.

Matthieu: It is.

Jeremy: All right. Then what about like the workers and that sort of use case where, so maybe I have ... So I know like Laravel has a queuing system and there's some other things built into those. If I just wanted to build a worker function, do I do that as part of the framework, or is that something that I separate out into its own thing?

Matthieu: Yeah. That's a very interesting question. The answer to me is not really easy. It depends. The Laravel queue system and Symfony has one as well, which is called Symfony Messenger. Those are particularly pretty nicely built. They, for example, handle automatic centralization and decentralization of your classes into strings that can be sent to SQS. They handle pre-TRI data cues, all of that. If you start using AWS Lambda in the SQS integration, some of these features become useless. Like the retry in the later queue mechanisms.

You can use the one from SQS. Now, do you need the automatic centralization and decentralization of objects? Sometimes. Sometimes not. Now, depending on the case, whether you want to get your hands dirty or exchange messages across languages and across applications, you may not want to use a framework. Writing Lambda functions with class in those that's perfectly fine.

If you enjoy the high level service that Laravel may provide, then use Laravel queues. That's fine. That's why we've been working lately on integrating those frameworks and their specific queue system with Lambda and SQS.

Jeremy: Right. All right. Then what about like ETL tasks and batch processing or other scripts? A lot of use cases for Lambda functions, you see people spinning up infrastructure and shutting it down or just kicking off some processing, batch processing. Maybe reading from Kinesis or doing something like pulling data from S3. You know, obviously that's all possible to do with this, but is there an interface into those other services via Bref, or is it just a matter of using the PHP SDK?

Matthieu: Yes. To me, that's about using the PHP SDK. I haven't seen a lot of weird use cases. I think it's also related to the culture of PHP. PHP is a node language and I would say to match your language and ecosystem. Just mentioning Lambda sometimes it feels like a buzzword. People can be reluctant to look into those things. I understand that. It's perfectly fine to go with mature and boring technologies. Yeah. I think going with Kinesis and DynamoDB, that's a use case that is not that popular in PHP.

Yeah. I think that's the thing. It's also really frightening when I say to people that Lambda has a maximum execution time of 15 minutes. To me, it seems huge and you can split large tasks into parallelized smaller tasks, but it's still sometimes a huge step for some teams to refactor their code and change it so that it fits on Lambda.

Jeremy: Right. Yeah. That's interesting because I do think that that PHP mindset is wrapped around relational databases like using MySQL or something like that. I'm just built into that mindset, but that'd be interesting. Do you think that there'll be a culture or a cultural shift that PHP people start embracing DynamoDB more, or do you think eventually Bref will have first class support for DynamoDB?

Matthieu: Yes. I definitely want to do that. I started working on a DynamoDB, I don't want to say ORM, because it doesn't make any sense, but a DynamoDB SDK. In PHP there is obviously the AWS SDK, but for DynamoDB, for example, it's not as good as the JavaScript implementation. It's really, really hard to send objects and get back objects from DynamoDB for example. There are some things lacking specifically in PHP.

I want to cover DynamoDB. I also really, really want to cover EventBridge and its schema registry. I think it's really, really interesting. Yeah. I think there's a lot of stuff to do here that could be really interesting, but that's a lot of work to do.

Jeremy: Yes. I know. Well, I wrote the DynamoDB toolbox, which is a layer on top of the JavaScript version, which tries to make that even simpler, which is ... Yeah. Getting data in and out of DynamoDB is fairly simple, but being able to serialize it the right way and make sure that you do all the right formats and stuff can get a little bit confusing. Let's not even get started on querying and single table design and all that kind of stuff.

Matthieu: Yes. Yeah. Oh-

Jeremy: Go ahead.

Matthieu: Yeah. Just thought about a use case I heard about like six months ago. I thought it was really interesting and really like PHP. It was a team that had a really old Legacy PHP application and that's an approach I found really interesting. The application was so old and so Legacy that they couldn't just edit the code, add new features and they were really desperate about it. What they did instead was migrate the MySQL database to use Aurora and then use the Aurora trigger to run PHP code whenever there were modifications on some specific rules.

That's how they managed to breach a very old Legacy application with Lambda and with their new stack where they could forward information from the old database into the new system. I thought it was a really clever way to do it.

Jeremy: Yeah. That's interesting. Speaking about Legacy applications, so Symfony and Laravel, we talked about this earlier. There are a lot of those applications out there, right? Laracon and Taylor Otwell, I had him on the show a long time ago and he had just released Laravel Vapor, which is the serverless version of Laravel that allows you to deploy it there.

That was something though that was proprietary and you had to host it in his environment, or I guess you would deploy to your environment, but there's a deployment engine in there. Bref though, you have support for Symfony and Laravel. Can I just take an existing Symfony app for example, and drop it into serverless using Bref?

Matthieu: Yes and no. I mean, it should be that easy. It's not that easy. You would have a few very easy things to configure. For example, logging and sessions and the cache. I think that's about it. Those are three things. That's a single line of code to change most of the time. It's really easy to do. Then there's usually a few more things that actually you write to the file system. That's the main thing to the file system. You have to change that.

If it's information you want to keep, you have to use Amazon S3. Thanks to abstractions in Symfony and Laravel, it's usually fairly easy to change. Yeah. These things can take time. I would say, depending on the complexity of the application, you could spend half a day, maybe a day or two on that migration. If you have a very old ... I mean, a Legacy application that's much harder. That's where I think it would be maybe too much work.

Jeremy: Right. Let me ask you this question, because I always find that as you're building Greenfield applications, that you've got a lot more choices. Old and boring, I don't know if I would consider Laravel and Symfony too old. I mean, they are kind of old at this point, but boring. I mean, for people who are in that ecosystem they certainly love them. Is that something where if you were building a new serverless application and you were going to use PHP because that's the language you're familiar with, would you still suggest that people build using one of these frameworks? Or do you suggest that they start thinking single-purpose functions?

Matthieu: I have seen a lot of web agencies building two or three websites every month. They use Laravel. They know their tools and they know everything that they have to know in Laravel. They are really productive. For them using AWS Lambda is mostly a question of not having to deal with infrastructure. For them, it makes total sense to keep using Laravel and start using Lambda. Then Lambda will become boring. Then they will have to write a small Chrome task or a small worker, and they'll get started with actually writing proper functions.

To me, that's a very valid way to do that because if Laravel works on Lambda and if it's cheap and if it scales well, and if it just does the job, then why not? Now, I don't know if you were a startup and you want to invest into the future or you're a large company and you want to write microservices then yeah. It would probably make more sense to get started into a proper serverless architecture. I think each of those has its use cases.

Jeremy: Right. Yeah. Now, what do you do? You do a lot of consulting work. When you're writing Bref applications, do you do proper functions and just use or you don't use those extra libraries and frameworks?

Matthieu: Yeah. I would say it depends. If I am creating the application and I know that the team that will maintain that in the long run is able to pick that up and use it, then yes, I'll do as serverless as I can. In some cases that's just like I write the prototype or I do a migration and I will hand that off to a team that doesn't know a lot about Lambda. I really adjust based on the people that will work on that project later. For my own project, I use serverless everywhere.

Even I'm starting to write some experimental runtimes that go even further than what I'm doing at the moment. I'm exploring as much as I can. I think there's still a lot to do. I follow a lot what arc.codes and people at Begin are doing. Yeah. I forget the name of-

Jeremy: Brian LeRoux.

Matthieu: Exactly. Yes. I loved the approach of actually changing infrastructure and changing completely the way we create and organize our applications. That makes sense. I think it's a step that is really high. I'm sure we will get there, but I think it's also fine to take time into adapt to the actual needs for right now.

Jeremy: Right. Yeah. I think that you bring up a really good point, and that's just that this idea that the complexity of serverless ... Like a few years ago it was easy. It was simple, straightforward. Then as more use cases started popping up and more people were like, "Oh, I need to be able to do this or I need to be able to do that." It becomes more complex. This is an ongoing conversation that I have with a lot of my guests. What are your thoughts on the complexity of serverless in general?

Because if you're just uploading code or you go to the console, type in something for node, it's easy enough. Now, you're talking about deploying with a framework using a custom runtime. Maybe potentially building your own framework where you have to use your own framework or use a framework like Bref to do that. I mean, I think there's a value to just having these simple onboarding experiences. Like I already know Laravel or I already know Symfony. What are your thoughts on where this is going in complexity?

Matthieu: Yes. Actually, I wanted to say that when I think about Laravel Vapor, for example, I think that's a really good approach because with Laravel Vapor, Taylor has complete control over the framework and over what the framework will do. He designed the framework with the new versions to run specifically ... I mean, to be completely compatible with Vapor. Vapor is super easy to use. I think this is a really good approach. It looks like a very good product. Same with Begin.

I think those approaches make a lot of sense. Just like with serverless components that we've seen lately, it makes so much sense. As you said, it's simple yet it's getting more and more complex every month. Maybe we need another radical simplification yet again, but this time around maybe the codes or how we set all the things up.

Jeremy: Right. Yeah. I mean, obviously as the author of a framework as I know when I build tools, open source tools, I do it because it's something that I need. It's something that was missing. Do you think frameworks are the answer? I mean, because again, I've used frameworks all the time. It's not something I shy away from, but the question is, do we need frameworks for serverless or should we get to a point where we don't need them because the cloud provider, whoever, is handling most of that complexity for us?

Matthieu: Exactly. Yes. That's a very, very interesting discussion. The more I use serverless and services from AWS, the more I realize that these services replace parts of our frameworks. That's what I've been trained to use more and more lately with ... You have API gateway doing the routing. You can drop that off your framework. EventBridge with this even schema registry and schema validation and mapping to actual TypeScript objects or whatever, this is actually what Symfony Messenger is about.

This library is being replaced by a service, an infrastructure service. There are so many examples of that. You can do CQRS with again services. I think eventually the framework may actually move into the cloud and the code framework will actually be an infrastructure framework. I'm not sure where eventually we will arrive, but that's really, really interesting.

Jeremy: Yeah. No. I agree because I think it's one of those things where we try to ... So AWS gives us primitives, right? These simple things that we can use. Lambdas is a primitive. DynamoDB is a primitive. SQS is a primitive, but we have to glue all these things together and you have cloud formation, serverless framework as an abstraction on top of that. You've got obviously Terraform and some of these other things. I'm just wondering though.

You know, I'm trying to ... I think you have unique insight here because as you're building a framework, what you're trying to do is you're trying to build a level of abstraction. You're trying to find a way to say, "Okay. Here are all these loose ends and I'm going to tie them together for you so you don't have to worry about that interconnection." I think that you just have a unique perspective on this. Do you think it's possible?

You mentioned about maybe moving the framework into the cloud. Is there something higher level, like a serverless components that either the cloud provider creates or something like serverless components or CDK?

Matthieu: That's exactly what I was-

Jeremy: Are those the answer?

Matthieu: Yes. Exactly. That's exactly what I was going to say. I don't know if it will be the serverless components. I don't know if it will be the CDK or a Begin-like solution. Myself, I've been working on a framework, a PHP framework built on Bref that actually configures a bit like serverless components, but specifically made for PHP and that looks a lot like in the Laravel approach, except there is no code. It's just setting up infrastructure.

Yes. There is a missing abstraction here. It will happen. I don't know how, but just to answer your previous question, I don't think the framework will die. It will just change a lot and it will change in shape.

Jeremy: Yeah. I think that makes a lot of sense. All right. Then just on serverless in general, because we have a few more minutes, I'd like to pick your brain if I could. You've been building a lot of serverless applications. Obviously a lot of use cases you can solve with it. You're focused on PHP, which I don't think limits in any way what you're doing. There's certainly a lot of other use cases that serverless or Lambda isn't ready for yet, or it can't handle yet.

Where do you see the future of serverless going? Do you see this eventually replacing containers completely or do you think that we're going to live in a hybrid world for a very long time?

Matthieu: That's a good question. To be honest, I'm not sure. It would make sense to me that eventually we would be assembling bricks and not doing that container thing or setting up servers, containers, whatever, just assembling stuff. Just like we can now directly connect some AWS services together without even having to write Lambdas together. The glue is just configuration that we write in yellow. For use cases like machine learning I've never used that so I'm not really good to speak on that, to be honest. Yeah. Getting up to a higher level of abstraction is just the way things go the way we go.

Jeremy: Right. Awesome. All right. Well, listen, Matthieu, thank you so much for joining me. This was a great conversation. If people want to find out more about you and more about Bref, how do they do that?

Matthieu: I have a blog, which is mnapoli.fr. They can go there. I have a few case studies, sorry, case studies about PHP websites migrated to Lambda with Bref. I do have a few more of them to write. There's obviously Bref website if they want to get started with PHP on Lambda. I do run a web ... Sorry, a newsletter as well that is related to serverless and specifically to PHP. When there's anything new in serverless I look at it and wonder, "Is this related to PHP? Is this useful to PHP developers?"

If so, I share about it. Finally, I am at the moment working on an interactive course. It's not ready yet. Hopefully, it will be in a month or so. My goal is to show developers, not just PHP developers, but developers that do not understand why serverless is interesting, what use case can be actually solved with serverless. That's something I've been working on and I'm really eager to finally release it.

Jeremy: Awesome. All right. You also had that cost calculator too, which I thought was pretty interesting.

Matthieu: Yes. Yes.

Jeremy: Yeah. All right.

Matthieu: Perfect.

Jeremy: I will put all of that in the show notes so that everybody can see all this stuff. Again, this was awesome. Thanks again Matthieu.

Matthieu: Thank you.

Episode source