BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage Podcasts Lin Clark on the WebAssembly Component Model

Lin Clark on the WebAssembly Component Model

The WebAssembly Component Model is a language-neutral approach to building web assembly applications in small units that can be assembled into a larger application. Using the metaphor of lego blocks, Lin Clark (a Senior Principal Software Engineer at Fastly) discusses WebAssembly Component model with Wes Reisz, including the background, roadmap, and design goals. Lin is a central figure working on WebAssembly (wasm), WebAssembly System Interface (WASI), and now WebAssembly Component Model. Today on the podcast, Lin and Wes talk web assembly and the work happening around developing the component model.

Key Takeaways

  • WebAssembly Component Model is a language-neutral approach to building web assembly applications in small units that can be assembled into a larger application. 
  • WebAssembly excels in the edge environments because it has extremely fast and secure. The web assembly execution engine can run JavaScript 13 times faster than the same application running in a V8 isolate in a serverless function.
  • WebAssembly specs layer on top of each other. The core spec is intentionally very low level and very unopinionated. JavaScript integration is another spec that is layered on top of the WebAssembly spec. These layers allow wasm to remain flexible and to be used in different ways.
  • Composability, language neutrality, reusability, security are all design goals of the WebAssembly Component Model.

Introduction [00:22]

Wes Reisz: WebAssembly, abbreviated Wasm, is a binary instruction format for stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client-server applications. Today, if you're building out an app with WebAssembly modules, there are some challenges. One of which is there's a lot of glue code that has to be written. All that glue code can potentially make you miss out on some of the very reasons that you wanted to use WebAssembly in the first place. These are things like resource efficiency, your code size, or maybe just performance.

Also it adds (and increases) the amount of complexity it takes for you to build your applications. WebAssembly Component Model is hoping to cut through some of this glue code by defining rules, things like how that memory is used, how modules are instantiated, called, destroyed, and the communication between them. So it's hoping to help these modules work more efficiently and reduce some of that mental overhead for the developer.

Hello and welcome to the InfoQ podcast. My name is Wes Reisz. I'm a platform architect working on Tanzu at VMware, and one of the hosts of the podcast. In addition to podcasts, I chair QConPlus, which will be this November 1st through 12. QConPlus is an online-only version of the QCon software conference where you can expect curated content around modern software practices like the things that we're going to talk about today with WebAssembly Component Model that matter right now in software development. QConPlus is a practitioner-led conference that focuses on learning success and failures from domain experts. So head over to qcon.plus to learn more.

Today on the podcast, we're talking to Lin Clark. Lin is a senior principal software engineer at Fastly. Lin is a central figure working in the WebAssembly (wasm) space. also with WebAssembly system interface (WASI) space, and now the WebAssembly Component Model, which I have no idea what the short version of that is but we'll ask her. She's also a code cartoonist, as anyone who's read her blog posts or seen presentations from her with our almost signature cartoon style of graphics that are really great. We'll talk a bit about that too.

Lin is a co-founder of the Bytecode Alliance, which is an industry collaboration to implement the proposals being delivered by the WebAssembly working group within the W3C, specifically around use cases outside of the browser with a focus on security. Today on the podcast we're talking about all these things and so much more. So as always, thank you for letting us join you on your jogs, walks, and commutes.

Welcome, Lin.

Lin Clark: Hi there. Great to be here. Thanks for inviting me.

Wes Reisz: I'm excited to get this going. All right. So my first question, I hinted at it here in the opening. WebAssembly is wasm. We've got WASI. What is the WebAssembly Component Modules, short name?

Lin Clark: We do not yet have an acronym for that one, which I feel like we're getting so many of these acronyms. It's now getting confusing, even for those of us who are deep in the weeds here. So we might just leave it at the WebAssembly component model.

Wes Reisz: We have to have an acronym. There are just too many around WebAssembly.

Do you still maintain and create the medium site on Code Cartoons? [03:15]

Wes Reisz: I guess my real first question is the first time I heard your name or got introduced to you was really around code cartoons. I think when I first saw those, I'm thinking 2015, 2016, somewhere around there. Most of those I think were on React and Flux that kind of the stuff I was seeing. Do you still do the cartoons? Obviously, they're there with the presentations and blog posts, but do you still do the cartoon?

Lin Clark: I do. And I always get a little sheepish when people ask me this question because it's one of those situations where the shoemaker's children have no shoes. I created the medium site Code Cartoons after a presentation I gave because it just resonated so much with people using these cartoons as a way of explaining these technical topics. So I started the medium log just cause it was quick and easy to get up and running. And then I quickly, after that, stumbled upon this cool thing called WebAssembly and got really into that. And all of a sudden didn't have enough time to really maintain the site. But I kept doing cartoons. So you'll find the cartoons in places like Mozilla hacks blog and the Bytecode Alliance blog. But my project now that I actually do have a little free time again is I already have a new version of the site that I'm developing. It should be live in the next couple of weeks.

Wes Reisz: Very cool. Very cool.

Lin Clark: Fingers crossed. We'll have something up for the listeners here.

Wes Reisz: So hopefully by the time you listen to this, there'll be something out or soon to be out. I love those. They do resonate. Julia Evans, she does the eZines that really resonate too. I don't know. It's something about taking technical topics and breaking down into cartoons that helps, I don't know, grok the content. That works really well, at least for me. Okay. So I mentioned there was React and Flux. You're doing some front-end stuff. And then you discovered this WebAssembly that we're going to be talking about today. Was that just because you were looking for something stronger in the browser? 

What got you into this cool thing called WebAssembly?

How did you get involved with WebAssembly? [05:04]

Lin Clark: Well, I really got nerd sniped into it I have to say by one of the best nerds snipers of all time. My colleague, Luke Wagner, was one of the co-creators of WebAssembly. He's the one who had the initial idea for asm.js, Which then provided a foundation for the ongoing WebAssembly standardization effort. And anyone who's worked with Luke will tell you what a delight it is. He has this really quick, insightful way of approaching problems, a lot of different kinds of problems too. But it's not just that. He has this knack for finding ways to incorporate people with different perspectives and different skillsets and really making them want to join him, be enthusiastic about joining him and building out his vision. So that's what makes him such a good nerd sniper.

And so I was getting interested in Rust at the time, and this was around December of 2016. And they just introduced support for compiling to WebAssembly. And so I figured a good way for me to get involved in Rust was for me to start playing around with this. But then when I ran into some problems, I figured I should talk to somebody who understands WebAssembly more. And we happened to be at the company all hands. We were all working at Mozilla at the time. We were at the company all hands. So I plunked myself down next to Luke and just started peppering him with questions. And by the end of that week, I came away with my mind racing, figuring out how to do a five piece code cartoon about WebAssembly, which then became part of Mozilla's announcement of the MVP a few months later. And ever since then, it's been such a joy to work with the team that I continued to collaborate with them and then formally became a part of the team.

How did you end up at Fastly after Mozilla? [06:46]

Wes Reisz: That's awesome. That's a great story. So you mentioned Mozilla. Now you're at Fastly. Obviously, some things happened there with Mozilla. What led you to Fastly? What brought you there?

Lin Clark: We were really lucky. Our team had been collaborating with Fastly for two or three years already.

Wes Reisz: Is it the WASI stuff?

Lin Clark: Yeah. Both on the Cranelift compiler and with WASI. And then they were also one of the co-founders of the Bytecode Alliance. So we just have this really well-established relationship with the team there. It almost felt like we were part of the same team already. And so when things were getting tougher, we had a really great place to go for the outside the browser work. There's still a great team at Mozilla working on the inside the browser, working on the engine that runs WebAssembly inside of Firefox. Then we continued to collaborate closely with them. But Fastly was a better place for funding the outside of the browser language toolchain work.

Why is WebAssembly important at the edge? [07:37]

Wes Reisz: So why the edge and WebAssembly? I think I know, but from your words, what makes WebAssembly an interesting use case for Fastly at the edge?

Lin Clark: WebAssembly is great for edge environments for a lot of the same reasons that it's good for serverless in general. These are environments where you'd need performance, but you also need security because you're running multiple customer's code on the same machine sometimes in the same process and because a WebAssembly engine is pretty small... it's a pretty contained spec. They have a really fast startup and a small footprint. And additionally, the design of WebAssembly makes it so you can do some pretty cool optimizations.

So for example, our team has taken an innovative approach to running JavaScript, which makes us so that our startup time for JavaScript is 13 times faster than Node for the same application running in a serverless function. So you get this new level of performance with WebAssembly. But sometimes there's a trade-off between performance and security. Because of the way that the WebAssembly sandbox... it has this built-in sandboxing. Because of that, the customers also get really good isolation, which you need for security in these multi-tenant situations.

Wes Reisz: As you're talking, one of the things that... you're describing containers to me a lot, like the new unit of deployment for software where you we write everything into containers. What is the reason that the WebAssembly runtime was preferred over something like a container in this use case?

Lin Clark: Well, containers are great. As an industry, we've progressively moved things to be more performant and have a smaller footprint. So, of course, we had VMs, but the startup time on a VM is way worse than a container. And of course, the footprint is larger too. Containers improved that. WebAssembly is once again an improvement upon that. And so it actually means that at Fastly, we start up a new WebAssembly runtime on every single request. So basically every single time you hit is conceptually a cold start, but because we've gotten the latencies down so low you don't even notice that it's a cold start. You're getting this peak performance just from startup of the whole thing.

Wes Reisz: That's awesome. What is the startup time?

Lin Clark: So these numbers were taken before I actually joined Fastly. The work that they had done showed a startup time of 50 microseconds. But we've actually been improving that since then. I don't know what the current numbers are off the top of my head, but it is really impressive.

Wes Reisz: But literally with every request there's a cold start. That's very impressive. As you and I were chatting about what would be good topics, the WebAssembly Component Model came up. So let's start off and kind of dive in. First off, what is the WebAssembly Component Model?

What is the WebAssembly Component Model? [10:21]

Lin Clark: Well, the metaphor that we've been using for the component model and for components is the metaphor of Lego blocks. This is how modern software is being developed if you look at ecosystems like NPM in the JavaScript ecosystem or PyPI in the Python ecosystem. The way that developers start coding, building applications, in those ecosystems is to pull down all of these little Lego blocks that they then assembled together. And it's really easy to assemble these Lego blocks together.

We want this kind of experience for the WebAssembly ecosystem. But instead of being limited to a single language, these Lego blocks can be in any language that compiles to WebAssembly. And you should be able to put all of these components that are written in these different languages together. So with this, the developer can build applications and have that really good developer experience that you have in a good language ecosystem today but still have the isolation and language neutrality that you would get from something like microservices.

Wes Reisz: Okay. So as you're describing that, I'm showing my age here, but I can't think of but COM, EJB, CORBA. That's kind of what that sounds like to me. Am I off base?

Lin Clark: No, not at all. We have a lot of the same goals as the goals that the folks developing those technologies did. However, we have the good fortune of being able to look at the past 20 to 30 years of successes and failures and mistakes and learn from those. So the design and implementation is pretty different. But that's just how this iterative cycle of improvement works in this industry. Some day 20 to 30 years from now, somebody is going to be looking at what we built and envisioning a radically new, even better way to tackle these same problems.

Wes Reisz: All codes, legacy code after you earned it, right?

Lin Clark: Exactly.

What’s the difference between a wasm module and the wasm component model? [12:06]

Wes Reisz: Okay. So help me understand a little bit more. So wasm module, isn't it already a component that you can compose? I guess what's this doing?

Lin Clark: Well, that's a really good question. The WebAssembly core spec is what specifies the modules that we have in WebAssembly. But that spec is intentionally very low level and very unopinionated. So this means it's very flexible. So for example, people would think that the WebAssembly core spec would say something about JavaScript. It actually doesn't. The JavaScript integration is another spec that's layered on top of the WebAssembly spec. And that means that we can have other languages that have layers or in the case of the component model, something that abstracts across those languages that layers on top of the WebAssembly core spec. So the WebAssembly core spec does have some limitations because of this flexibility, like the fact that what you're passing back and forth between modules is really low-level data types.

Wes Reisz: Yeah, like int32s, right?

Lin Clark: Exactly. Integers and floats. Yeah. And so that's very flexible, but not very ergonomic for a lot of the use cases. So this component model layer, this layer on top of the core spec basically wraps the WebAssembly module and gives it some of these extra powers that provide the ergonomics that make it easier to compose applications out of these modules that have been wrapped in components. But there are some niche use cases where you wouldn't want to have all of this extra baggage. If you're just going to for this niche use case only have a single module then you probably don't want to have the extra burden of implementing component model things. So that's why we want to keep this layered model where we have the flexibility for WebAssembly to be used in other ways, but we have the component model for the ergonomics and for the composability.

What is the roadmap for WebAssembly Component Model? Is it something I can use right now? [13:54]

Wes Reisz: Lin, one question I wanted to ask you is where are we when it comes to these WebAssembly components? Are they something I can use today or is there still a little bit of runway before I can use them?

Lin Clark: There's still a bit of runway before you're going to be able to use them. We've fleshed out the design of a lot of the necessary standards pretty well at this point, but we still need to do prototyping. That implementation feedback is really critical to making sure that you've gotten the specification right. So we are doing that as a team. Other teams are also working on the implementation. And so we're in that process. We're going to be comparing notes and then pushing the proposals forward to finalizing them.

How are these features being released? [14:34]

Wes Reisz: So will it be like a big bang with everything is released or will I be able to use types and not work with int32s and floats sooner rather than later, or how has it being released?

Lin Clark: So that's a really good question. It will be released proposal by proposal as they make it through. So these are pretty decoupled. Interface types might make it to what's called stage four, stage five, before module linking, which is another part of the component model. That's totally fine. You get a lot of benefits just from interface types itself. And so these will be moving ahead as fast as they can within the individual proposals.

Wes Reisz: Just out of curiosity, what's that mean? Six months, two months a year, do you have any idea?

Lin Clark: Well, that's always the hard question in standards.

Wes Reisz: Shake the magic eight-ball.

Lin Clark: But we do think that we have a really good start on the prototyping. And so far, it seems like things are falling into place pretty well. So I am optimistic that we will have something, fingers crossed, by the end of this year, early next year. But of course, as you said, it is shaking the magic eight ball. So you never know.

How do all these things in the WebAssembly space connect together? [15:41]

Wes Reisz: We talked about the component model. We talked about WebAssembly, but there's also WASI, so WebAssembly system interface. And that has to do with connecting to the host that it's running on, right? How do all these things connect together?

Lin Clark: There's a part of the component model called the Interface Types Proposal, and that is the specification that we're using to define all interfaces. And these interfaces are both component-to-component interfaces so that these components can be passing records and streams and other fancy data types back and forth. WASI is also being defined in terms of interface types. And so that actually means that you can use these rich types to communicate with the host, which is great, but it also means that because these are defined using the same language, the same set of types. So a WASI module, you might have a WASI module such as WASI file system on some hosts, but then you might not have it on other hosts. Like an IoT device might not have a file system.

Lin Clark: What if you want to run code that requires WASI file system on an IoT device? Well, then because we're using the same set of types to define interfaces and defining these interfaces in the same way, somebody can actually define a component that basically polyfills this WASI API that would normally be native and store those files in the WebAssembly's linear memory instead.

What are some of the design goals that the WebAssembly Component Model? [17:03]

Wes Reisz: That makes sense. Okay. So you just mentioned one of the design goals of language neutrality. What are some of the design goals that the WebAssembly Component Model is hoping to achieve?

Lin Clark: Yeah, so language neutrality is of course a really big one. That's been a goal of WebAssembly since the very beginning. Another one is reusability. We want these components to be as reusable across different environments, whether this is in the browser or the cloud or IoT devices. And if you look in the JavaScript ecosystem, that's an example of where reusability across these different environments wasn't really a design consideration in the beginning because they were thinking of JavaScript as just being in the browser.

But then of course, with Node, it became something that was being reused across these different environments. And now they've had to go through a pretty painful process, a long and painful process, of retrofitting reusability across these different environments. For example, making Node modules and ECMAScript modules compatible with each other. So we want to start with reusability across environments in mind so that we don't have to go through that painful retrofitting process later on.

Another key principle is composability. We want the developers in this ecosystem to be able to download modules that haven't been developed specifically for their use case but then apply those modules for a variety of different use cases. But for this to work, these components, they can't be making implicit assumptions about how the modules that they are interacting with work. So we need to basically turn these into black boxes so that you don't have to infer what's happening on the other side of the component boundary.

Another principle that's really important is security. There are some complicated words to describe the kind of security that we're going after here, like capability-based security or the principle of least authority, but basically what it means is we need to make sure that each part of the code can only do the things that it's supposed to do and can't go around opening files or connecting to random servers willy-nilly.

How does the WebAssembly Component Model improve security for wasm modules? [19:11]

Wes Reisz: Let's double click on that one just for a second. So you wrote a blog post a few years ago on a supply chain attack. So the first question, I'm assuming the component model will give us some protection against that type of attack. So, the first question is is that true? And then second, could you describe that supply chain attack and then how the component model can isolate and protect from that type of attack?

Lin Clark: The component model does help with that. It gives us some tools to help with that. And WASI is where we're really going after that problem. So a good example of this is in Node a couple of years ago there was a module that actually stole people's Bitcoin wallets, the money in people's Bitcoin wallets. And the way that that happened was the malicious module developer created what seemed like a useful small package that just formatted alerts that were then going to be shown to the user. So really all it should be able to do is take in a string of bytes and turn it into a different string of bytes. But because nobody was really watching what the module developer was doing after it had been pulled in as a dependency in this Bitcoin wallet, they added code that would then open up the wallet and open a connection to a remote server and send the funds to the remote server.

Now you can get rid of a whole lot of these errors by just making it so that a module that is doing something simple, like just formatting a string, does not have access to the file system or to opening a connection across the network. And one of the nice things about WebAssembly is it's very statically analyzable. We can actually tell all of the capabilities, all of the things, the system calls that a module needs just from the module signature. In this case, if this developer had then tried to add the capability to open this file and send it across the network, the maintainers of the wallet application would have seen the change in the signature of his module. And they would have seen that it was now asking for the ability to open files, for the ability to open these network connections. And they would have had a way to say, "Hey, this does not seem right for this module."

Wes Reisz: Okay. So I'm not connecting how WASI or a component model is giving me that guardrail.

Lin Clark: So by default, a WebAssembly module can't interact with anything at all. The only thing a WebAssembly module can do by default does lots and lots of math that heats up your computer. So for any interaction that it wants to have with the outside world, you need to pass in a function that gives it the ability to do that interaction. And because of that, that gives us that stack analyzability that I was mentioning before. So the WASI APIs that we are developing are those functions that are getting passed in to give these modules the ability to interact with the outside world.

How do you deal with things like concurrency and parallelism when you’re building a modular system like this that supports so many different language paradigms? [22:09]

Wes Reisz: There's a couple of other questions that I had written down that I wanted to ask you a little bit about. So we're talking about this ability to be kind of language-agnostic... language neutrality rather. But I'm curious about how do you deal with things like concurrency. Different languages have code routines. They have async functions; the shared memory models are different. How did you approach this? Is there share everything, share nothing? How do you approach this with concurrency and memory management?

Lin Clark: Well, that is a really good question. One of the big ideas that has come out of the WebAssembly community over the past few years is this idea of "Shared Nothing Linking." Basically, as an industry started to understand the best practices and develop best practices, we've realized that having a globally mutable shared state is not really a great way when it comes to making sure that your code is maintainable or that it is secure-

Wes Reisz: Scalable.

Lin Clark: Scalable. It's not a great way to work. So we're starting with the idea of having shared nothing. Now, there are certain cases where you have two modules that you do want to have shared access to memory, but for that you need to explicitly opt into it. So if you are doing something where you need to share a memory, you can have two modules that are inside of a component that are sharing memory, directly acting, poking at the same memory at the same time, potential for race conditions if you want that. You can do that. But across the boundaries between components, it gets harder to do that kind of stuff.

And when talk about concurrency, concurrency and parallelism show up in a few different places. So I'll give a few examples here. So for example, you might have some JavaScript code that is making async calls either within its own boundaries or to another module. In that case, the developer is just going to use the tools that JavaScript makes available. And that's because it's all within the same language. So it's using that one concurrency model. We can trust that it's using a single concurrency model. But once you're making async calls across components, then we can't be sure that the concurrency model is the same between these two components.

So Luke, the person who nerd sniped me into WebAssembly, who I mentioned before, he's working on some really impressive proposals to ensure that WASI doesn't have to pick a single concurrency model. With this proposal, we can just have a single WASI API that can be used in either a callback or a co-routine manner. And the engine will take care of the coordination. And then of course, when we talk about parallelism, you might want to parallelize work across multiple cores in a machine. And so for this, the Intel folks are driving a proposal called WASI parallel that actually gives you some controls to do that kind of thing.

What are you most excited about when it comes to the WebAssembly Component Model? [26:06]

Wes Reisz: So we talked about language neutrality. We talked about security. We've talked about concurrency and parallelism. We've talked about shared nothing. We talked a little bit about dev ex, developer experience with working with these. What stands out for you? What are you really excited about that the web component model will give you?

Lin Clark: Well, it's hard to say. I think I am one of those folks who has drunk the Kool-Aid. I think it's all super cool, but if I had to pick a few, I think that the language neutrality is really amazing. The fact that we can have these components that are written in completely different languages that can easily inter-operate with each other in the same way that when I'm downloading an NPM module I don't need to think about how I'm going to get the data across the boundary, the fact that we can now do this across languages I think is really phenomenal.

I also think that the security benefits could be a game-changer. We're going to, of course, have to see how it works out in practice, but at least in the way I'm seeing it come together and shape up, it seems like this could solve a lot of the problems that are only getting worse over the last few years with security.

How do you experiment with some of these new features with WebAssembly? [26:06]

Wes Reisz: As I was kind of prepping for this, I was talking to one of our program committee members for the conference, Werner Schuster. I was telling him about this podcast. And I asked him what kind of questions that he might ask you. And one of the things that he wanted to know was specifically around how new features are introduced to WebAssembly. So when you talk about some of these new features, how are they introduced? Is there a feature flag where you can kind of enable things? Is it just each new version that comes out? How do you experiment with some of these new features when maybe it's not fully available to developers? What's that look like in the WebAssembly community?

Lin Clark: Well, this is unfortunately still a bit of a problem, and there are different answers for different parts. So the WebAssembly core spec there were discussions earlier when the MVP was being developed around feature flacking. But as far as I'm aware, that has not yet moved forward. But we can do something different with things like WASI. So with WASI, as I was saying, everything is an import. And so we can actually tell if your platform doesn't support the things that you're importing, and could even potentially give you a pathfinding way to find the polyfills that can actually get you from the manifest, what your application requires, to what this platform actually has.

And we also have this idea that is currently in the WASI repo but is going to move over to interface types for something called optional imports. If there's some functionality that would be nice to have but you don't actually really need it, you can fall back to something else if needed, then these optional imports would give you a way to do an if to say, if you actually do have this then I'll use it, if not fall back gracefully.

Wes Reisz: Wait a minute. You're saying that a community of people heavily influenced by some things that went on in the JavaScript world see if what's going on in the environment can fall back to another mode in polyfill. That was considered? Go figure.

Lin Clark: Indeed. Very surprising.

What is the Bytecode Alliance? [28:09]

Wes Reisz: So surprising. All right. So as we talked about in the intro, you co-founded the Bytecode Alliance. I want to do a quick shout-out to Bytecode Alliance. What is it? What was its goal? Tell me a bit about it.

Lin Clark: That sounds great. Yeah. So the Bytecode Alliance was started... We started it because we kept running across people who were trying to solve the same problems as us. And we kept saying, "We should be collaborating." And this is on implementation rather than standardization. The standard says what a piece of code should do, but it doesn't say how that piece of code should actually achieve that result. And so we needed people to collaborate with us on actually implementing and figuring out how to achieve that result.

So we got together with a number of companies working on the same kinds of tools and founded the Bytecode Alliance. We're collaborating on all sorts of different kinds of tools for outside the browser use cases. That includes the Wasm time runtime, which you could use in the cloud. You can use it on IoT devices. You can use it in a bunch of different places. And a lot of the members of the Bytecode Alliance are using it in different places. The Cranelift Code Generator is one of our projects. We also are building out tools that make it easy for different languages to use interface types that we're adding to different language toolchains. So those are the kinds of projects that we work on collaboratively within the Bytecode Alliance.

Wes Reisz: Well, very cool. Lin, thank you so much for taking the time to sit down and chat about this. It sounds like there's some exciting stuff.

Lin Clark: Indeed. Thank you so much for having me.

More about our podcasts

You can keep up-to-date with the podcasts via our RSS Feed, and they are available via SoundCloud, Apple Podcasts, Spotify, Overcast and the Google Podcast. From this page you also have access to our recorded show notes. They all have clickable links that will take you directly to that part of the audio.

Previous podcasts

Rate this Article

Adoption
Style

BT