Cause & Effect Podcast
Nov 26, 2024
#1: Adopting Effect at Zendesk with Attila Večerek
In this episode, Attila Večerek, Tech Lead and Staff Engineer at Zendesk, joins our host Johannes Schickling to discuss how Zendesk incrementally adopted Effect in a polyglot environment with a large codebase.
In this episode, Attila Večerek, Tech Lead & Staff Engineer at Zendesk, joins our host Johannes Schickling to discuss how Zendesk incrementally adopted Effect in a polyglot environment with a large codebase.
Effect is an ecosystem of tools to build production-grade software in TypeScript.
Song: Dosi & Aisake - Cruising [NCS Release]
Music provided by NoCopyrightSounds
Free Download/Stream: http://ncs.io/Cruising
Watch: http://ncs.lnk.to/CruisingAT/youtube
- (00:00) - Intro
- (03:13) - Being an engineer at Zendesk
- (06:05) - Challenging the status quo
- (13:10) - Introducing TypeScript at Zendesk
- (20:22) - Adopting fp-ts
- (25:19) - The transition from fp-ts to Effect
- (31:00) - DX adopting Effect
- (37:15) - Implementing a Kafka consumer with Effect
- (42:18) - Dependency injection
- (48:33) - The power of TypeScript & Effect
- (53:03) - Onboarding developers to Effect at Zendesk
- (01:15:37) - Excitement for Effect Cluster
- (01:19:30) - Outro
Transcript
- 01:00:00like the dependency injection,
- 01:00:02like dependency management as well.
- 01:00:04It's just so great with Effect.
- 01:00:07I feel like I'm much more
- 01:00:09incentivized to write unit
- 01:00:11tests and I don't know how other people
- 01:00:13think about engineers at companies like
- 01:00:16Zendesk and like Facebook and Google, like big companies
- 01:00:21like how they
- 01:00:22deal with these things
- 01:00:23on a day-to-day basis.
- 01:00:24In the end, like it doesn't matter
- 01:00:26how skillful or experienced you are.
- 01:00:29It comes down to incentives all the time.
- 01:00:31Like you do things that you
- 01:00:33are more incentivized to do.
- 01:00:35So, If a language or a framework or a library
- 01:00:39makes something really easy to do,
- 01:00:42you will do it regardless, whether it's
- 01:00:44the right thing to do
- 01:00:45or the wrong thing to do.
- 01:00:49Welcome to "Cause & Effect," a podcast
- 01:00:52about Effect, the TypeScript library,
- 01:00:53and ecosystem helping engineers build
- 01:00:56production-ready software.
- 01:00:58I'm your host, Johannes Schickling, and I've
- 01:01:00been building with
- 01:01:01Effect for over four years.
- 01:01:03With this podcast, I want to help others
- 01:01:05understand the benefits
- 01:01:07and powers of using Effect.
- 01:01:09In this episode, I'm talking to Attila
- 01:01:11Večerek, a tech lead at Zendesk
- 01:01:14and long-term user of Effect.
- 01:01:16In this conversation, we talk about the
- 01:01:18challenges of building production-grade
- 01:01:19software in TypeScript
- 01:01:21and how Zendesk ended up adopting Effect
- 01:01:23in one of their main products,
- 01:01:25serving millions of users every day.
- 01:01:28Let's get into it.
- 01:01:29Welcome Attila to the very first episode
- 01:01:32of the Cause & Effect Podcast.
- 01:01:34How are you doing?
- 01:01:36Thank you.
- 01:01:37Thank you, Johannes.
- 01:01:37I'm so happy to be here.
- 01:01:39Uh, I'm doing pretty well.
- 01:01:40Thank you.
- 01:01:41How about you?
- 01:01:42I'm doing fantastic.
- 01:01:43Really looking forward to doing
- 01:01:45this podcast and to
- 01:01:46do it together with you
- 01:01:47since I think we've been in
- 01:01:49touch now for quite a while.
- 01:01:50We met like half a year ago, also
- 01:01:53for the first time in person at the
- 01:01:55first Effect Conference in Vienna.
- 01:01:58And yeah, really excited to do this
- 01:02:00together and share more
- 01:02:02your story of like
- 01:02:03discovering Effect and using Effect.
- 01:02:05So you're using Effect at Zendesk, but
- 01:02:08would you mind giving a quick
- 01:02:10introduction of who you are?
- 01:02:13What is your role at Zendesk?
- 01:02:14What have you done before?
- 01:02:16And then we can dive deeper.
- 01:02:19Sure thing.
- 01:02:19Hey everyone.
- 01:02:20My name is Attila, Attila Večerek and
- 01:02:22I've been at Zendesk
- 01:02:25for almost seven years.
- 01:02:26It's going to be seven years
- 01:02:27exactly this year in October.
- 01:02:29Currently I'm a tech lead at a
- 01:02:32team in the Guide organization, which
- 01:02:35is responsible for the
- 01:02:38help center part of Zendesk.
- 01:02:41So, if you see any help center
- 01:02:43articles or community
- 01:02:45and stuff like that,
- 01:02:47that's, that's what I do.
- 01:02:48And most recently I also got the
- 01:02:51responsibility of re-vamping
- 01:02:53our customer satisfaction feature.
- 01:02:55which is one of our most used
- 01:02:57features besides like the core product,
- 01:02:59which is ticketing itself.
- 01:03:01And yeah, I'm very excited about that.
- 01:03:03And that's actually the feature
- 01:03:05which is built using Effect.
- 01:03:08That sounds awesome.
- 01:03:09Yeah.
- 01:03:09I'm excited to hear more about that and
- 01:03:11go in depth, but would you
- 01:03:13mind describing a bit more of, given
- 01:03:15that, there are, I think,
- 01:03:17several thousands of engineers at Zendesk
- 01:03:19and not all code there is written
- 01:03:22with Effect, that might change at
- 01:03:24some point, but would you mind giving
- 01:03:27a quick overview of, what it means to
- 01:03:30be an engineer at Zendesk?
- 01:03:31So Zendesk is really large, we
- 01:03:34have many sub orgs and, or
- 01:03:37departments and each of them, even at the
- 01:03:40team level, like there are huge
- 01:03:41differences, we're truly a polyglot
- 01:03:44company when it comes to languages
- 01:03:46and different kinds of tech stacks.
- 01:03:48I still think most of our code is
- 01:03:51still written in Ruby.
- 01:03:53The company started with
- 01:03:54Ruby and Ruby on Rails specifically.
- 01:03:57We have two large Ruby monoliths.
- 01:04:00both of them I have to
- 01:04:01interact with from time to time.
- 01:04:03That's, that's always
- 01:04:03an interesting
- 01:04:05experience, especially
- 01:04:06when you've been working with Effect
- 01:04:08for a while and then you have to go back
- 01:04:10to Ruby and like, Oh, okay.
- 01:04:12Things are a little bit different here.
- 01:04:14But besides Ruby, there's also like a
- 01:04:16ton of Java, some Scala, some
- 01:04:20Golang, yeah, and obviously
- 01:04:22TypeScript mostly for
- 01:04:23front-end, but, we
- 01:04:24have also some companies that we acquired
- 01:04:27who brought in a lot
- 01:04:28of backend TypeScript.
- 01:04:30And yeah, we have some, some of the
- 01:04:32TypeScript on the
- 01:04:33backend in Guide as well.
- 01:04:36So it sounds like Ruby has always
- 01:04:39been the majority of code and still is.
- 01:04:42Is there any technology, any
- 01:04:43language that you feel like is really,
- 01:04:46on its way in and might replace Ruby
- 01:04:49as the primary
- 01:04:49language maybe at some point?
- 01:04:51That's really hard to tell.
- 01:04:52I don't think Ruby will go away ever.
- 01:04:56These huge monoliths, they're here to
- 01:04:59stay with us for
- 01:05:00until Zendesk will exist.
- 01:05:02I'm pretty sure of that.
- 01:05:04We had some initial thoughts of breaking
- 01:05:07the monoliths down, but it's really
- 01:05:09hard to justify these efforts, when
- 01:05:11it comes to product and, and like the
- 01:05:14business needs of the company.
- 01:05:16So for all the startups out there,
- 01:05:19like if you start with a technology
- 01:05:21and you become like large company and
- 01:05:23really largely successful, all the
- 01:05:26tech that, that you accumulate for all
- 01:05:28those years, that's going to probably
- 01:05:29stay there for, for a while.
- 01:05:31So yeah, maybe, maybe think about twice
- 01:05:34about what you start with.
- 01:05:36Not all this tiny decisions, but like the
- 01:05:38major ones, it's, it's good
- 01:05:39to put some thought into it.
- 01:05:41Oh yeah, for sure.
- 01:05:42But I mean, Zendesk is a very,
- 01:05:45profitable and very great company.
- 01:05:48So I suppose it wasn't
- 01:05:49the worst stack decision.
- 01:05:51If it led Zendesk to this point
- 01:05:53today and given that you, are also
- 01:05:57now leaning more into TypeScript, I think
- 01:06:00there there's, you can probably use the
- 01:06:02best tools for the appropriate jobs.
- 01:06:05But speaking of TypeScript, I think this
- 01:06:07is one example of like a theme
- 01:06:10that I'm noticing, which is that you seem
- 01:06:12to challenge the status quo a bit.
- 01:06:15when it comes to engineering
- 01:06:16within Zendesk where you see, okay,
- 01:06:19this is how things are done.
- 01:06:20And then, you seem to, send some
- 01:06:23ways to do things possibly better.
- 01:06:26And this is, I think we're using some
- 01:06:28colleagues, if I understood
- 01:06:29correctly have, at some point looked
- 01:06:32at TypeScript and said, actually,
- 01:06:34this is a bet worth making.
- 01:06:36Can you share that anecdote?
- 01:06:37Yeah, sure thing.
- 01:06:38So maybe just to understand for maybe
- 01:06:41people who are not familiar
- 01:06:42with Ruby on Rails, Ruby is a
- 01:06:44dynamic programming language.
- 01:06:46It's great for really one
- 01:06:49engineer or tiny teams that know the code
- 01:06:53base by heart, it makes
- 01:06:55them really efficient.
- 01:06:56So productivity wise,
- 01:06:57it's, it's terrific.
- 01:06:59So starting with Ruby for Zendesk was
- 01:07:01definitely a good bet.
- 01:07:03It allowed them to have like a
- 01:07:05velocity in the beginning that was
- 01:07:07absolutely crucial to become successful.
- 01:07:10But you know, working with a dynamic
- 01:07:13type language, especially like
- 01:07:16with a heavy OOP focus where you have
- 01:07:19lots of like design patterns.
- 01:07:22I'm not sure if you have worked with
- 01:07:24teams where people would argue
- 01:07:26like, Oh, you know what, for this
- 01:07:28feature, we should
- 01:07:29use this design pattern.
- 01:07:31And then the other side would be arguing,
- 01:07:33no, no, no, uh, look at,
- 01:07:35switch your mentality.
- 01:07:36Like, you have to look at the problem
- 01:07:38this way and then they
- 01:07:39bring up adapters and whatnot.
- 01:07:41And DDD and all these things.
- 01:07:43At a certain scale, it becomes fighting
- 01:07:46an uphill battle all the time because you
- 01:07:49have to be fully aligned with all
- 01:07:51the people who work on the code base.
- 01:07:54You have to agree on these things.
- 01:07:56Like what are the design
- 01:07:57patterns that we are introducing?
- 01:07:58Okay.
- 01:07:59Are we shifting to a
- 01:08:00different design pattern?
- 01:08:01Are we re-architecting
- 01:08:02redesigning our modules?
- 01:08:04Are we taking out and
- 01:08:06extracting reusable modules?
- 01:08:08And how do we do that?
- 01:08:10Are we doing some, you know, some
- 01:08:12module boundaries within rails and
- 01:08:14use rails engines or some other ways of
- 01:08:16enforcing these module boundaries?
- 01:08:18So all of these decisions, like you
- 01:08:20really have to pull the same rope in the
- 01:08:23same direction and then it's good.
- 01:08:25But at some point, now let's say you have
- 01:08:27this huge monolith, which we have,
- 01:08:29and you have 50 people or even hundreds
- 01:08:31and thousands of
- 01:08:32people contributing to it.
- 01:08:34Having this alignment across the
- 01:08:36entire organization is really hard.
- 01:08:39So what you end up having is a mixed bag
- 01:08:42of things and, you know, parts of
- 01:08:44the repo, use one design better.
- 01:08:47Another part uses another one.
- 01:08:49And then there's this new design better
- 01:08:51that you're pushing for some
- 01:08:52modularization and
- 01:08:54then that's a migration.
- 01:08:56And then there's tons of migrations going
- 01:08:58on at all time, like five, 10, 15
- 01:09:02different types of
- 01:09:03migrations in a code base.
- 01:09:04And then let's say you're a contributor
- 01:09:06who just wants to implement like a tiny
- 01:09:09bit of a feature, which is necessary in
- 01:09:11that repo so that the other service can
- 01:09:15communicate with it.
- 01:09:16I don't know.
- 01:09:16You, let's say you want to emit some
- 01:09:18events from
- 01:09:19the main monolith and then over
- 01:09:21Kafka or over whatever message bus so
- 01:09:24that you can consume
- 01:09:25those events in your microservice.
- 01:09:28Well, suddenly you'll see five or six
- 01:09:30different examples of how to emit
- 01:09:32domain events, or Kafka.
- 01:09:34So what do you do then?
- 01:09:36How do you find the people, that know
- 01:09:39what's the current status quo, or
- 01:09:42will you just blindly pick the one that
- 01:09:45is the most prominent?
- 01:09:46I mean, that's, there's no problem going
- 01:09:48with that route either, because if it's
- 01:09:51the most prominent thing and let's say
- 01:09:53it's something that
- 01:09:53we're moving away from.
- 01:09:55You can just commit to that and it will
- 01:09:57be moved away from with the rest.
- 01:09:59But then, you know, if you pick something
- 01:10:01in between, then that also brings the
- 01:10:03risks that the people who are doing that
- 01:10:05migration will just
- 01:10:07have bigger and bigger
- 01:10:08headaches because now they need to
- 01:10:10migrate different kinds of ways of doing
- 01:10:13things into this one,
- 01:10:14one way of doing thing.
- 01:10:15so these are the biggest problems
- 01:10:17that I see with Ruby, alignment,
- 01:10:20constantly fighting an uphill battle.
- 01:10:23You introduce a new feature, but at the
- 01:10:25same time you introduce a bug because
- 01:10:27you miss something and there's constant
- 01:10:29action at the distance.
- 01:10:30You change one part of the application,
- 01:10:33which has some
- 01:10:33unforeseen or unpredictable
- 01:10:35effects on another part of the
- 01:10:37application because
- 01:10:39everything is reusing everything.
- 01:10:41That makes a lot of sense.
- 01:10:42So it rather sounds like you're,
- 01:10:45you're running into some like social
- 01:10:47alignment issues where you just have so
- 01:10:50many engineers, like an all probably very
- 01:10:52brilliant and with like the best
- 01:10:54intentions trying to design it with their
- 01:10:57understanding of the world.
- 01:10:58But if you have thousands of engineers,
- 01:11:00this can lead to some, some very wild
- 01:11:04different directions and to enforce that
- 01:11:06alignment, I think if
- 01:11:08you're, if you don't
- 01:11:09have a types type system at your
- 01:11:11disposal to help with
- 01:11:13that, to be even aware of
- 01:11:15like, Hey, here's like some divergence.
- 01:11:17We're unopigniated maybe, or we
- 01:11:19tolerate both, but even to have some
- 01:11:21visibility into this and
- 01:11:23help drive the alignment.
- 01:11:25I think this is where a
- 01:11:27type system can help a lot.
- 01:11:28And I suppose that is what's what has
- 01:11:30made you so interested in TypeScript.
- 01:11:33Yes, absolutely.
- 01:11:35So that, that was one of the biggest
- 01:11:36driving forces behind the
- 01:11:38adoption of some language
- 01:11:40that is statically typed.
- 01:11:42it has tons of
- 01:11:43benefits, not just like this alignment.
- 01:11:45Very recently, I just actually had to
- 01:11:47go into one of these large Ruby
- 01:11:49monoliths and there's a feature flag
- 01:11:52that I introduced and some different
- 01:11:54behavior for when the feature flag
- 01:11:56is enabled and now this feature flag has
- 01:11:59been rolled out fully
- 01:12:00for, for some months now.
- 01:12:03So I was looking into removing the,
- 01:12:06if.else branch for the feature flag
- 01:12:09to keep only the logic that's basically
- 01:12:12used now that it's fully rolled
- 01:12:14out and by removing that one line of
- 01:12:17code, I broke like
- 01:12:19hundreds of unit tests.
- 01:12:21Because the unit tests had no idea that
- 01:12:24there was like a dependency on some HTTP
- 01:12:28call somewhere down the line.
- 01:12:30So now I have to find like a place where
- 01:12:32I can maybe permanently mock this call to
- 01:12:37a specific endpoint for all the
- 01:12:39tests forever, because I
- 01:12:41cannot pinpoint like the
- 01:12:42hundreds of different places
- 01:12:44where this is exactly called.
- 01:12:46So I have to mock it
- 01:12:47like on a general level.
- 01:12:49So, so these are also kinds of issues
- 01:12:51that you bump into
- 01:12:52and using languages and
- 01:12:54frameworks like this which is going
- 01:12:56to be another segway into Effect, I guess,
- 01:12:58later on with the
- 01:13:00dependency injection.
- 01:13:01Yeah, most certainly.
- 01:13:03So it sounds like you're building
- 01:13:05production grade software at scale at
- 01:13:09Zendesk in many different flavors,
- 01:13:12many different technologies, but at some
- 01:13:14point you've introduced TypeScript and
- 01:13:17that's the foundation for the services
- 01:13:19and products you're building.
- 01:13:21What was that that journey like?
- 01:13:24So you now have a type system to help
- 01:13:26with many things, but I suppose it still
- 01:13:29has not given you the silver bullet that
- 01:13:32makes it super easy to build production
- 01:13:34grade software.
- 01:13:36So what are some of the challenges you
- 01:13:38were still facing and possibly still
- 01:13:40face today and were
- 01:13:41you reaching for Effect?
- 01:13:43So if I have to reflect back on the
- 01:13:45time when we were introducing TypeScript
- 01:13:47at guide for the first time, I think
- 01:13:49obviously what we wanted to avoid where
- 01:13:51all of these problems that come with, uh,
- 01:13:53shared monoliths. We just wanted some
- 01:13:56some service, which is nicely isolated
- 01:13:58and we have our own
- 01:14:00deployment schedule, which
- 01:14:02is basically on demand.
- 01:14:03We don't need to deploy it on a
- 01:14:05weekly or biweekly cycles.
- 01:14:08And then of course the maintenance,
- 01:14:09improvements,
- 01:14:10because now you have a type
- 01:14:11system, so if you make a change in one
- 01:14:13place, the compiler
- 01:14:15will aid you in updating
- 01:14:18all the other call sites.
- 01:14:20So that, that was
- 01:14:21obviously one thing.
- 01:14:22But we also wanted to make sure that
- 01:14:25we don't get into these like reliability
- 01:14:27issues that we were having with the box.
- 01:14:29So like type safety was
- 01:14:31really important for us.
- 01:14:33Then we're looking into how to, because
- 01:14:36there are many different ways how you can
- 01:14:38write TypeScript, right?
- 01:14:39Like you can be really
- 01:14:40lenient and allow any.
- 01:14:41Right.
- 01:14:42You can typecast here and there.
- 01:14:45The language is quite flexible.
- 01:14:47You can use as much type safety as
- 01:14:49you want, or you can
- 01:14:51go towards the other end
- 01:14:52of the spectrum and use like the most
- 01:14:55brutal compiler
- 01:14:57options that are out there
- 01:14:59and make it super, super type safe.
- 01:15:02And then you even start thinking about,
- 01:15:04okay, how do we do
- 01:15:04end to end type safety?
- 01:15:06Right.
- 01:15:06Because there are certain things that
- 01:15:08come out of your system.
- 01:15:10Like on these boundaries of your system,
- 01:15:12you have a HTTP request coming in.
- 01:15:15Maybe HTTP request going out.
- 01:15:17Kafka message coming in.
- 01:15:19Like you need to parse these and at
- 01:15:22the inbound of your system, you have to
- 01:15:26be able to work with
- 01:15:27it with a static type.
- 01:15:29Right.
- 01:15:30So, so how do you do all of these things?
- 01:15:32Rolling it manually is really tedious
- 01:15:34with all the type checks at runtime.
- 01:15:38Especially if you have like really
- 01:15:39complex objects it
- 01:15:41is really hard to do that.
- 01:15:43So obviously you can compose like start
- 01:15:45at the leaves and then
- 01:15:46build up all of these,
- 01:15:47but that's a lot of work.
- 01:15:48So we started looking into other,
- 01:15:51like maybe even, even other programming
- 01:15:54paradigms like with, with Ruby, like of
- 01:15:56course there's like a
- 01:15:57ton of OOP stuff, but
- 01:15:59then with TypeScript, we were realizing,
- 01:16:01oh, okay, maybe we can actually leverage
- 01:16:04like, some functional programming
- 01:16:05concepts to build
- 01:16:07more composable software.
- 01:16:09Because one TypeScript
- 01:16:10service was not our goal.
- 01:16:13We were already thinking in multiple
- 01:16:15TypeScript services and in the end it did
- 01:16:17become reality and then we wanted to
- 01:16:19share code in between them.
- 01:16:21And then how do you do that?
- 01:16:22Well, we came up with a mono repo of
- 01:16:26different libraries that we can use that
- 01:16:29implement like Zendesk concerns, things
- 01:16:32like sharded database
- 01:16:33clients that know how to
- 01:16:35connect to our sharded database and yeah,
- 01:16:39many, many other
- 01:16:40libraries like this, these
- 01:16:42internal ones, these
- 01:16:43productivity booster ones.
- 01:16:44So we started implementing those and then
- 01:16:47we're like, okay, but
- 01:16:48they are like different
- 01:16:49libraries like suddenly they have this
- 01:16:52library has this API.
- 01:16:53This library has another one.
- 01:16:54I want to use them in combination.
- 01:16:56And then you think about how to
- 01:16:58hype all the APIs
- 01:16:59in the way that they
- 01:17:00nicely flow.
- 01:17:02So that's when one of my colleagues found
- 01:17:04fp-ts and that sounded really great.
- 01:17:07Obviously it had a huge
- 01:17:08learning curve for us.
- 01:17:10None of us were really much into
- 01:17:12functional programming.
- 01:17:13I only remembered some stuff from
- 01:17:15university, but definitely
- 01:17:17have it, haven't had like
- 01:17:19hands-on experience and then learning fp-ts
- 01:17:22like people who
- 01:17:23learned it, they probably
- 01:17:24know how hard it is because you don't
- 01:17:27have like real documentation.
- 01:17:29You have like API
- 01:17:30interface documentation.
- 01:17:32What gave you the confidence to take the
- 01:17:35leap of faith to go
- 01:17:36to reach for fp-ts and
- 01:17:38make that the
- 01:17:39foundation for your libraries?
- 01:17:41Um, desperation.
- 01:17:44I don't know.
- 01:17:46I was just really, I think we all just
- 01:17:48wanted to avoid another monolith.
- 01:17:52And obviously we, we cared a lot about
- 01:17:55these tiny libraries
- 01:17:57that were meant to be
- 01:17:58shared across the different services and
- 01:18:00different services need to do different
- 01:18:03things, right?
- 01:18:04Like they're in a different domain. So it's really hard to
- 01:18:06predict what API is the right one.
- 01:18:09So as long as we can stick to something
- 01:18:11and make it
- 01:18:11composable, that should work for
- 01:18:15most of the cases.
- 01:18:16I mean, that was at least our idea.
- 01:18:18The execution was rough.
- 01:18:21We were iterating
- 01:18:22on this group of
- 01:18:23libraries and we followed,
- 01:18:25versioning a strategy that would version each library.
- 01:18:30At the same time.
- 01:18:31So even if we make a change in one
- 01:18:32library, we would bump
- 01:18:33the version of all the
- 01:18:35libraries just to make it easier for the
- 01:18:38consumers to understand what version of
- 01:18:40one library works with another.
- 01:18:41So we opted for this and then the
- 01:18:45iteration was so fast on these APIs.
- 01:18:48We just kept in introducing breaking
- 01:18:50changes all the time because we
- 01:18:51discovered new and new ways
- 01:18:54of using these libraries.
- 01:18:58And so within the span of three years, I
- 01:19:00think we went from
- 01:19:01version zero to version
- 01:19:0327. Our consumers were
- 01:19:05not happy about this.
- 01:19:06Let's just say this. Right.
- 01:19:09So I suppose fp-ts at that point was
- 01:19:11already quite the pill to swallow for
- 01:19:14you all where you convinced yourself to
- 01:19:16do it, but then to have other API
- 01:19:18consumers that did not intentionally say
- 01:19:21like, yes, we want to bring in fp-ts
- 01:19:23into our life, but that's just the way
- 01:19:25how you offered it to them.
- 01:19:28That was probably even, even trickier.
- 01:19:31So, but that's what you started out with.
- 01:19:33And I suppose you, you chose that for
- 01:19:35the, for very
- 01:19:36understandable reasons, such
- 01:19:38as the dream of composability and code
- 01:19:41reuse and making all your systems more
- 01:19:45resilient, but it came at a price of
- 01:19:48like a rather esoteric flavor,
- 01:19:50particularly for the ones who were not
- 01:19:54getting up in the morning saying, yes,
- 01:19:56I want to do functional programming, but
- 01:19:58you just want to do proper programming,
- 01:20:01uh, maybe in TypeScript.
- 01:20:03So, and if I understand correctly, this
- 01:20:06is where you have been kind of like
- 01:20:09running into growing pains of fp-ts and
- 01:20:12building larger systems out of this.
- 01:20:14And at some point you found Effect.
- 01:20:18So tell me about that.
- 01:20:19Oh yeah.
- 01:20:20So that, yes.
- 01:20:22So basically with this fp-ts we
- 01:20:24were trying to build
- 01:20:25something similar to Effect.
- 01:20:27We wanted to have a system which allowed
- 01:20:30our consumers to
- 01:20:32do proper dependency
- 01:20:33injection with all the config that we
- 01:20:36provided so that when they start their
- 01:20:38program, like if the config is wrong, it
- 01:20:41will just not deploy.
- 01:20:43We want it to eliminate as
- 01:20:45many foot guns as possible.
- 01:20:47Obviously resource management was
- 01:20:49another big thing that
- 01:20:50we were looking into.
- 01:20:51Like how do you properly handle like all
- 01:20:54the interrupt signals coming from
- 01:20:56Kubernetes when it's trying to kill
- 01:20:59or restart your container.
- 01:21:00These things.
- 01:21:02They require a lot of effort and they're
- 01:21:06not easy things to do, especially if you
- 01:21:08want highly composable solution.
- 01:21:11So I think one of my colleagues,
- 01:21:13was my partner in crime when it came
- 01:21:16to introducing fp-ts to the
- 01:21:20organization at
- 01:21:20large, he found Effect.
- 01:21:23I don't know how he found it, but he
- 01:21:24found it and it was maybe in 2021.
- 01:21:28I don't remember.
- 01:21:29I'm so bad with years, especially because
- 01:21:31it was like the pandemic there.
- 01:21:33And suddenly like two
- 01:21:35years felt like one or half.
- 01:21:40But around the time, it was weird.
- 01:21:43Time flow flew, flew differently.
- 01:21:46But he did found it and it wasn't
- 01:21:48like we were jumping on it immediately
- 01:21:50because at the time there wasn't really
- 01:21:54such a huge buzz around it.
- 01:21:56Like it is nowadays.
- 01:21:58Also
- 01:21:58didn't have a stable API.
- 01:22:02So we were for about at least a year, we
- 01:22:05were mostly observing Effect from the
- 01:22:06sidelines, we didn't talk to also no
- 01:22:08documentation at that point yet.
- 01:22:11Yeah, exactly.
- 01:22:12It was just another fp-ts for us
- 01:22:15from the sidelines looking at it, but
- 01:22:17it looked way better than fp-ts it
- 01:22:20looked like, okay, this is not just
- 01:22:23abstractions, this is
- 01:22:24also some implementation.
- 01:22:26Finally, something that
- 01:22:27makes our lives easier.
- 01:22:29It's like a general programming
- 01:22:30framework, how to build like resilient
- 01:22:32services and all the dependency injection
- 01:22:37resource management,
- 01:22:39configuration management,
- 01:22:41building the layers of dependencies.
- 01:22:43That's all taken care of for you.
- 01:22:45So, so that looked really promising.
- 01:22:49And as I mentioned, like for a year, we
- 01:22:51were just looking and watching,
- 01:22:53Effect and its development.
- 01:22:55And then later when it felt like, okay,
- 01:22:58now, now it seems like it's, it's
- 01:22:59like stabilizing
- 01:23:00around some sort of an API.
- 01:23:03We still don't really agree with some
- 01:23:05namings, of some concepts, which
- 01:23:08then also changed name and everything.
- 01:23:10And now it's like much, much better.
- 01:23:12But we were, that that's, that's when
- 01:23:14we started to seriously
- 01:23:16consider adopting
- 01:23:17it on some, some project.
- 01:23:20We didn't really know
- 01:23:21which project should it be.
- 01:23:22We didn't really want to go right into
- 01:23:25the migration of an existing fp-ts
- 01:23:27project, because we
- 01:23:28didn't know how to do it.
- 01:23:30It was a little bit weird because
- 01:23:32from fp-ts we had all these reader
- 01:23:34task, eithers, and we, we could
- 01:23:37intuitively see how it would map to an
- 01:23:39Effect, but we didn't quite understand
- 01:23:41how, how it would work with our flavor
- 01:23:45of fp-ts if you know what I mean?
- 01:23:47Like we built those abstractions for
- 01:23:49managing dependencies and
- 01:23:52resources and whatnot.
- 01:23:54Like how would that, how would we make
- 01:23:55the step from that to Effect?
- 01:23:58So what we ended up doing in the end, my
- 01:24:01team got this opportunity to rebuild
- 01:24:04the existing customer satisfaction
- 01:24:06feature and we are making
- 01:24:08it like more flexible, like it's almost
- 01:24:11on our end in the backend,
- 01:24:13we treat these customers satisfaction
- 01:24:15surveys as, as generic surveys,
- 01:24:18because like, what is the customer
- 01:24:19satisfaction survey?
- 01:24:20It's like you ask a bunch of questions
- 01:24:22and one question has to be how satisfied
- 01:24:25you are about whatever you're measuring
- 01:24:28against in our case, like satisfaction
- 01:24:30about how your ticket was
- 01:24:32handled by the support agent.
- 01:24:33But in the end, it's just a survey.
- 01:24:35It's a bunch of questions and different
- 01:24:37types of questions and whatnot.
- 01:24:38So it looked like a perfect opportunity
- 01:24:41for us to try Effect.
- 01:24:44Especially because there were, there
- 01:24:46was already like Tim Smart's
- 01:24:48SQL package, SQL effect, which is like
- 01:24:51the predecessor of effect SQL.
- 01:24:53So that, that was really good because our
- 01:24:55service needs to,
- 01:24:57interact with the database for sure.
- 01:24:59So, so that, that gave me
- 01:25:00a lot of confidence there.
- 01:25:02obviously, and now
- 01:25:03we're using Effect SQL.
- 01:25:04I'm trying to like being lockstep
- 01:25:08with all the development
- 01:25:09with Effect itself, the core
- 01:25:12library, and then also like all the
- 01:25:14satellites that the level
- 01:25:16one and layer one abstractions.
- 01:25:19So it sounded like this was like the
- 01:25:21initial prototype where you gave Effect
- 01:25:24or like the initial trial project where
- 01:25:26you went from observing the Effect
- 01:25:29development to actually getting your
- 01:25:31hands dirty and seeing, okay, is this
- 01:25:34fulfilling all of our dreams, how
- 01:25:36our world already got better through
- 01:25:38fp-ts but we've introduced a couple of
- 01:25:40like new problems and maybe some of our
- 01:25:42teammates or some of the other teams, uh,
- 01:25:45have a hard time with it.
- 01:25:46And that could be addressed by Effect.
- 01:25:48And so now you've adopted it.
- 01:25:50How did that go?
- 01:25:50How quickly were you up and running?
- 01:25:52How quickly were you productive?
- 01:25:54And, uh, also very
- 01:25:56importantly, what did other teams think?
- 01:25:59So before I actually get into that, let
- 01:26:01me just tell you that for us getting rid
- 01:26:05of fp-ts or moving towards something else
- 01:26:07is, was existential.
- 01:26:09Like there was no universe where we would
- 01:26:12be able to push for fp-ts, at
- 01:26:15least in our usage of fp-ts in a way we
- 01:26:19did at a larger scale.
- 01:26:21Like if we wanted this TypeScript service
- 01:26:23framework to fly and be useful for not
- 01:26:27just our two teams that used it, but also
- 01:26:30outside of our org for all the TypeScript
- 01:26:33native teams, who we acquired
- 01:26:35through the business deals and stuff.
- 01:26:37We really had to get rid of it.
- 01:26:38We had to find like an alternative and
- 01:26:40unfortunately there was like no real
- 01:26:44alternative, beside Effect.
- 01:26:46But I'll get into why this is
- 01:26:48actually a pretty good alternative also
- 01:26:50for teams that only
- 01:26:52use native node JS TypeScript.
- 01:26:55But yeah, so, after I
- 01:26:58tried Effect for the first time, so I
- 01:27:00think it was last year in June that I
- 01:27:04made the first Effect commit ever at
- 01:27:07Zendesk, getting up and running was
- 01:27:09fairly easy because I could get a
- 01:27:11skeleton of an application using our fp-ts
- 01:27:15based service framework.
- 01:27:17And then, yeah, I think one important
- 01:27:19thing that I need to mention is that,
- 01:27:22we're mostly building these services
- 01:27:24on graph QL and then we have graphQL
- 01:27:26Federation, so yeah, like lots of
- 01:27:29microservices, each owning their own
- 01:27:31domain and we call them sub graphs and
- 01:27:33then they compose into a super graph through
- 01:27:36the Apollo
- 01:27:36Federation solution.
- 01:27:38So this survey service
- 01:27:39was just another sub graph.
- 01:27:41So once I got to the point where I could
- 01:27:43start implementing the resolvers for the
- 01:27:47different graphQL objects and
- 01:27:49mutations and queries and whatnot, um,
- 01:27:51I was already, at that point I could
- 01:27:54finally use Effect.
- 01:27:56So I was using Effect in the beginning
- 01:27:58only at the resolver level of my
- 01:28:01application.
- 01:28:03So, so that went pretty well.
- 01:28:05Startup was very easy.
- 01:28:06And then obviously like I created like an
- 01:28:09application skeleton that I'm familiar
- 01:28:11with, and then the resolvers were Effect.
- 01:28:14And that nicely adapted into the
- 01:28:17promise based resolver because with
- 01:28:19an effect, you can run it as a promise.
- 01:28:21So that was perfect.
- 01:28:22And then after that, it was just
- 01:28:24like, okay, let's, let's start with this.
- 01:28:26Let's start with a simple Effect.
- 01:28:28Let's start with a dummy resolver.
- 01:28:30And then next step was
- 01:28:32let's add some validation.
- 01:28:33So we brought in Effect Schema and yeah,
- 01:28:36now that I mentioned Effect Schema,
- 01:28:37I think that's probably the
- 01:28:39best gateway drug into Effect.
- 01:28:41Like everybody needs input validation.
- 01:28:45Everybody that it's almost impossible to
- 01:28:48imagine a piece of software, like a,
- 01:28:51you know, an HTTP service that doesn't
- 01:28:54need input validation unimaginable.
- 01:28:57Yeah, I definitely agree.
- 01:28:58I mean, this is where, why Zod as a
- 01:29:00standalone library is also getting so
- 01:29:02popular, but I think people
- 01:29:05will see that their
- 01:29:06requirements will grow beyond just input
- 01:29:08validation where you maybe need to run some
- 01:29:12effectful
- 01:29:13code, like some, some
- 01:29:14code that can't go wrong,
- 01:29:16et cetera, as part of this validation,
- 01:29:17but then also critically, not just
- 01:29:20parsing and validating the code, but at
- 01:29:23some point you might also want to
- 01:29:25re serialize it as you, you don't just
- 01:29:27receive data, but you want to ship it
- 01:29:30over the wire to another
- 01:29:31service or to your front end.
- 01:29:33And then you're scratching your head
- 01:29:35because, okay, you have now this beautiful
- 01:29:37sod system that can validate and parse
- 01:29:40data, but now you want to go the other
- 01:29:42way around and that is impossible.
- 01:29:45And if you use a whatever, like you've
- 01:29:48created a class, a user class that you
- 01:29:50parse things into, and now you have your
- 01:29:52data expressed through like those
- 01:29:54classes or more complex data structures.
- 01:29:58And you want to call
- 01:29:58JSON.stringify on it.
- 01:30:01And suddenly stuff blows up.
- 01:30:03And this is where Effect Schema comes
- 01:30:05in and I completely agree.
- 01:30:07This is going to be my primary bet for
- 01:30:10what will be the, the main gateway
- 01:30:12drug that brings people to Effect.
- 01:30:14And it's has gotten so nice.
- 01:30:17I think this is where in the past where
- 01:30:18you've been using fp-ts
- 01:30:20you've probably used io-ts
- 01:30:21Effect Schema is written by the same
- 01:30:23person, but I feel like
- 01:30:25It's a new incarnation, of the
- 01:30:28same person who just made everything
- 01:30:29so much nicer to use so
- 01:30:31much easier to understand.
- 01:30:33So yeah, huge fan of that part.
- 01:30:35Absolutely.
- 01:30:36Same.
- 01:30:37I'm a huge fan of Giulio who does
- 01:30:39all of this, this work.
- 01:30:40It's just amazing.
- 01:30:41-big shoutout to Giulio. -yeah, absolutely.
- 01:30:46fp-ts and io-ts helped us so much in the
- 01:30:48beginning and now seeing him also do all
- 01:30:50of the work, for Schema at Effect and
- 01:30:54doing a lot of Effect documentation
- 01:30:55work as well, it's just, uh, yeah, it's,
- 01:30:58it's amazing to see that.
- 01:31:00So sounds like last year, last summer
- 01:31:02you've written your first Effect code at
- 01:31:05Zendesk, and I think you've been
- 01:31:08by the end of that year, you've been
- 01:31:10getting to a point where it could be
- 01:31:12rolled out and we've been just chatting
- 01:31:15before where you mentioned that this year
- 01:31:17it's getting released in GA.
- 01:31:19So, I suppose across like all
- 01:31:22production traffic, et cetera.
- 01:31:24So how's that gone?
- 01:31:26And how did your team like it?
- 01:31:28How, how was your experience?
- 01:31:30Yes.
- 01:31:31So my personal experience was, was great.
- 01:31:33Let's start with me and
- 01:31:34then we can go to the team.
- 01:31:36And then we can go
- 01:31:36like outside of the team.
- 01:31:40Yeah, I was taking
- 01:31:41really baby steps with effect.
- 01:31:42So after input parsing and
- 01:31:45validation the next big step was to
- 01:31:48interact with the database, obviously
- 01:31:50relying just on SQL effects was not
- 01:31:53enough because we have
- 01:31:55a sharded database.
- 01:31:58We have like this big shared sharded
- 01:32:00database instances that every
- 01:32:03application interacts with.
- 01:32:04So we had to write like a wrapper,
- 01:32:07for SQL effects that would read
- 01:32:09the configuration, create one SQL
- 01:32:12pool per shard node.
- 01:32:15So basically one for a writer, one for a
- 01:32:18reader, and then we would have like this
- 01:32:20big collection of writers and readers
- 01:32:22group by shards, and then every time a
- 01:32:26request comes in, we would have to figure
- 01:32:27out what is the shard ID reaching to the
- 01:32:30collection handle like short shard not
- 01:32:33found errors and stuff like this.
- 01:32:35Finally getting the shard, getting the
- 01:32:37pool for the writer or the reader
- 01:32:38that you currently need at the
- 01:32:40point where you need to
- 01:32:42like call the database.
- 01:32:43And then that's when we get the SQL
- 01:32:46effects, like the SQL client from the
- 01:32:48library at the time, like the pool is
- 01:32:51basically provided by that.
- 01:32:52And then that was great.
- 01:32:54once we got there, because then we
- 01:32:56could persist events.
- 01:32:58So one thing that I want to mention is
- 01:33:00like, we use event sourcing where exactly
- 01:33:04this two way bi-directional schemas,
- 01:33:07work really well, because on
- 01:33:10one hand, like when the request comes in,
- 01:33:13we do the input parsing and then that
- 01:33:17input represents almost the exact
- 01:33:21payload that we then write to the
- 01:33:24database which represents our event.
- 01:33:26So once we did the parsing, obviously we
- 01:33:29need to serialize it into, into a
- 01:33:32string that we can then push into a,
- 01:33:35into a text column in SQL.
- 01:33:38So yeah, that was a big thing.
- 01:33:40And then obviously the next step
- 01:33:42after the database client, there was
- 01:33:44like the HTTP layer where we might
- 01:33:47need to call like different HTTP
- 01:33:49services, especially around the feature
- 01:33:52flags and stuff like that.
- 01:33:53So yeah, really baby steps.
- 01:33:54And then eventually we added some
- 01:33:56level of observability,
- 01:33:59logging, tracing metrics.
- 01:34:01In the beginning.
- 01:34:02It wasn't really anything sophisticated.
- 01:34:04We were relying mostly on the data dog,
- 01:34:06tracing library defaults, which
- 01:34:08provided some level of detail.
- 01:34:12It didn't work very well.
- 01:34:13We didn't get very detailed traces,
- 01:34:15but it was good enough to see some
- 01:34:17traffic and what's going on at the, maybe
- 01:34:20let's say the GraphQL level.
- 01:34:22So everything that is an Effect,
- 01:34:24obviously we couldn't get any visibility
- 01:34:26into that, but then we switched to
- 01:34:29Otel eventually, and then things
- 01:34:30improved from there and then as the more
- 01:34:34I learned about Effect, the closer
- 01:34:36I was getting to turning the application
- 01:34:39into an end to end Effect.
- 01:34:42And today it's like fully Effect.
- 01:34:44So it's effect from top to bottom.
- 01:34:46Right.
- 01:34:46And I think this is a pattern that I've
- 01:34:49seen a lot both in the apps that I've
- 01:34:52been building and where I take, I've
- 01:34:53taken my first steps with Effect, but
- 01:34:56also in what I see how other people are
- 01:34:59approaching effect is like how
- 01:35:01nicely it can be adopted incrementally.
- 01:35:03Where if you think about your program as
- 01:35:05a tree, you can very easily start
- 01:35:09at like any layer of the tree, really
- 01:35:12like at any position, you can start
- 01:35:14out with the leaves and
- 01:35:15write those as effects.
- 01:35:17And then at some point, just run them as
- 01:35:20promises and assuming your, your other
- 01:35:22code is already like promises or
- 01:35:25async await based, you can just call your
- 01:35:28new effect code as good old promises.
- 01:35:32Or you can do it on the other way around.
- 01:35:35And at the root of your program, you
- 01:35:37can rewrite some
- 01:35:39parts that are maybe more
- 01:35:41for governing and overseeing the
- 01:35:43execution of your program.
- 01:35:44You can rewrite that with Effect, for
- 01:35:46example, request handlers, but then,
- 01:35:49still call out to promises and everything
- 01:35:51else of your program is still promises.
- 01:35:54Or you can do it somewhere in the middle
- 01:35:55and say, okay, at some point we're like
- 01:35:58in async await, we're going to rewrite
- 01:36:00some part in with effects, but then the
- 01:36:03stuff way further down,
- 01:36:05we'll call again as promises.
- 01:36:07And so you can mix and
- 01:36:08match as much as you want.
- 01:36:10But what I've typically seen is that
- 01:36:13people get very
- 01:36:14productive very quickly
- 01:36:15with like some incremental adoption.
- 01:36:18And then they see
- 01:36:19like, Oh, wait a second.
- 01:36:20That part is still not as nice.
- 01:36:22And that is some of the
- 01:36:23leftover promise code.
- 01:36:25And then in no time
- 01:36:27that's rewritten to effect as well.
- 01:36:29I think what is typically
- 01:36:31the case is the more
- 01:36:32you rewrite to effect
- 01:36:33that kind of collapses the amount
- 01:36:36of code typically like by half and
- 01:36:39shines a very bright light on some of
- 01:36:42the holes that you haven't yet
- 01:36:43covered such as error handling very
- 01:36:46often, like Effect kind of shows
- 01:36:48you a mirror and say like asks you like,
- 01:36:50Hey, here stuff could go wrong.
- 01:36:52Right.
- 01:36:53What have you done so far about it?
- 01:36:54Not really much.
- 01:36:56And so it forces you to do the right thing
- 01:36:59That sounds very familiar.
- 01:37:00What you've described.
- 01:37:01Absolutely.
- 01:37:02Writing Effect has
- 01:37:03a lot of knock on Effect.
- 01:37:06Pun not intended. On how you write
- 01:37:09maintainable code on a day to day basis.
- 01:37:12Things like obviously the error
- 01:37:13handling it's amazing.
- 01:37:15Very recently I implemented a Kafka
- 01:37:19consumer with
- 01:37:20effect, um, using Kafka JS.
- 01:37:23So I just wrapped Kafka JS in an Effect,
- 01:37:25API and then had like an
- 01:37:28abstraction for a consumer and then
- 01:37:30obviously the consumer can consume
- 01:37:32things, um, either message
- 01:37:34by message or in batches.
- 01:37:35So I just needed a message by message,
- 01:37:38type of consumption.
- 01:37:41So that's what my abstraction does.
- 01:37:44It creates a consumer and you pass in
- 01:37:46like the effect that hand a function
- 01:37:48that returns an effect that handles like
- 01:37:50the incoming message, the payload.
- 01:37:53It was just really beautiful to see
- 01:37:55how the different error cases
- 01:37:57all bubble up to the very root of
- 01:38:01your message handler.
- 01:38:03And then in Kafka, like when you consume
- 01:38:06the messages, it's super important to
- 01:38:08make a decision at that point.
- 01:38:10Like, do you drop the message
- 01:38:12or do you retry reprocess it?
- 01:38:14Right.
- 01:38:14You need to be able to make this decision
- 01:38:17for every single error case.
- 01:38:19And you know, you just have effect dot
- 01:38:21catch tags and then you have like a big
- 01:38:24dictionary, like a big, big object
- 01:38:26containing the tag of
- 01:38:27the error on the left side.
- 01:38:30And the error handling basically die
- 01:38:33or, or succeed with some error
- 01:38:36logging or whatever.
- 01:38:37So if you die, Kafka
- 01:38:38will reprocess the message.
- 01:38:40If you, if you succeed and you log it,
- 01:38:42well, you can either put it into
- 01:38:45like a dead letter queue or something.
- 01:38:47If you want to keep
- 01:38:49those messages around.
- 01:38:51But if that's not necessarily
- 01:38:53important because
- 01:38:54it's like time sensitive
- 01:38:55and if you don't process it now, then it
- 01:38:58doesn't make sense to process it like
- 01:38:59five days later, then you
- 01:39:01just discard the message.
- 01:39:03And before I would normally implement
- 01:39:06Kafka consumers like in Ruby or maybe in
- 01:39:10fp-ts, it was also, it was better, but I
- 01:39:14don't think I had it to this level
- 01:39:16of granularity because what we ended up
- 01:39:18doing in fp-ts was taking like the
- 01:39:21shortcut route where we would just return
- 01:39:23a generic error interface.
- 01:39:25Just to have like, yeah, you
- 01:39:26know, it can error, but we didn't know
- 01:39:29what kind of error later on as I got
- 01:39:31better with fp-ts, then obviously you
- 01:39:33would have different types of errors,
- 01:39:34which would also compose.
- 01:39:36but I haven't written a Kafka
- 01:39:38consumer with that,
- 01:39:39approach in fp-ts,
- 01:39:41but with Effect, it was just like so easy
- 01:39:43and it's so useful because you don't
- 01:39:47think about all these different kinds of,
- 01:39:51ways your program can fail.
- 01:39:54And my consumer is very simple.
- 01:39:57It receives a message.
- 01:39:59It parses it.
- 01:40:00writes an event and
- 01:40:02then calls another service.
- 01:40:03So basically three things, but there's
- 01:40:07like 15 or 20 different ways it can fail.
- 01:40:10And it's just like, wow, now I know
- 01:40:12everything every single way, how it can
- 01:40:14fail
- 01:40:15so what took me the most
- 01:40:16time was thinking about whether to
- 01:40:20discard or reprocess the message in the
- 01:40:22whole implementation
- 01:40:23proportionally the most time,
- 01:40:25but that makes a lot of sense.
- 01:40:27And I think that makes a difference
- 01:40:28between resilient and
- 01:40:30non-resilient software.
- 01:40:33I think a lot of TypeScript programmers
- 01:40:35are blissfully ignorant of the
- 01:40:40unhappy path of a program, but this is
- 01:40:44what ultimately makes your users very
- 01:40:46unhappy if stuff goes wrong.
- 01:40:49and a lot of times that is completely
- 01:40:51unrelated to whether
- 01:40:52the user has done something wrong as
- 01:40:54whether your servers have a bad day or
- 01:40:56whether you've migrated some infra and
- 01:40:58like some things is like hitting capacity
- 01:41:02or you're just hitting a blip somewhere
- 01:41:04and things go wrong and a user gets like
- 01:41:08an endless spinner or gets like undefined
- 01:41:12is not a function in their face.
- 01:41:14This is where like some backend
- 01:41:15engineers haven't done their homework.
- 01:41:17And I get it.
- 01:41:19It's really tricky.
- 01:41:21If you, if you're just like dealing
- 01:41:23with like catch error and then
- 01:41:26you have an any or unknown
- 01:41:27thing and what do you do with it?
- 01:41:29Yeah, maybe you bubble it around, maybe
- 01:41:32you log it, but to work with it as
- 01:41:36nicely as like structured type data that
- 01:41:39you return from a function, that's what
- 01:41:41you get with Effect and
- 01:41:42you can handle it so nicely.
- 01:41:45That was actually fun to
- 01:41:46deal with the non happy path.
- 01:41:48Yes.
- 01:41:49And I think you
- 01:41:49touched upon it very well.
- 01:41:51It's fun.
- 01:41:52You don't feel like it's something that
- 01:41:56you have to do, but the language or the
- 01:41:59library like doesn't really provide a
- 01:42:01good way for you to manage.
- 01:42:02And then it's like just a headache.
- 01:42:04It's really fun.
- 01:42:05To handle these cases in Effect.
- 01:42:08And it just has such a great effect on,
- 01:42:12on your reliability, on the
- 01:42:16reliability of your software.
- 01:42:18The other thing that I noticed was also
- 01:42:22in terms of
- 01:42:23maintainability and testability,
- 01:42:25like the dependency injection,
- 01:42:27like dependency management as well.
- 01:42:30It's just so great with effect.
- 01:42:33I don't have to worry
- 01:42:34about mocking things extensively.
- 01:42:38I just build a fake dependency and
- 01:42:41provide that instead of, instead
- 01:42:43of the real one, the live one.
- 01:42:44And I feel like I'm much more
- 01:42:48incentivized to write unit
- 01:42:50tests and I don't know how other people
- 01:42:53think about engineers at companies like
- 01:42:57Zendesk and like Facebook and Google,
- 01:42:59like big, big companies, like how they
- 01:43:02deal with these things
- 01:43:03deal with these things
- 01:43:03on a day-to-day basis.
- 01:43:06In the end, like it doesn't matter
- 01:43:07how skillful or experienced you are.
- 01:43:11It comes down to incentives all the time.
- 01:43:13Like you do things that you
- 01:43:15are more incentivized to do.
- 01:43:17So if a language or a framework or a
- 01:43:21library makes
- 01:43:22something really easy to do,
- 01:43:24you will do it regardless, whether it's
- 01:43:27the right thing to do
- 01:43:28or the wrong thing to do.
- 01:43:29It's just like this.
- 01:43:30I don't know if there's like a law or
- 01:43:32this, but it's
- 01:43:33definitely a psychological effect.
- 01:43:36This, this is one of my favorites
- 01:43:38paradigms or
- 01:43:39guidelines in programming
- 01:43:42or in life, in principle,
- 01:43:45which is like make the right thing easy.
- 01:43:48And that is, I think Effect makes
- 01:43:51some really hard things
- 01:43:54that are the right thing
- 01:43:56as easy as they can be.
- 01:43:58And so easy that it's fun doing things
- 01:44:02like error handling or structuring
- 01:44:04the hierarchy of your program in a
- 01:44:06nice way, in the as nice way as you could
- 01:44:10possibly do it in TypeScript, that's a
- 01:44:12huge lift and that's
- 01:44:13what Effect enables you.
- 01:44:15And I think sounds
- 01:44:16like dependency injection.
- 01:44:17That's probably if you're in your Effect
- 01:44:20adoption journey, that typically happens
- 01:44:22sort of like maybe in the second week
- 01:44:25when you're using Effect
- 01:44:26after you've like rewritten
- 01:44:27a whole bunch of like
- 01:44:29promise code, et cetera.
- 01:44:31Maybe you've now like finally cleaned up
- 01:44:33some of your tech depth
- 01:44:34around error handling.
- 01:44:36And then you realize, okay, there's still
- 01:44:38like some
- 01:44:38global state we mutate
- 01:44:40to kind of pass things around, or we just
- 01:44:43have like this big blob of
- 01:44:45like properties we're
- 01:44:46like kind of pulling
- 01:44:47through like all of
- 01:44:49our function vacations.
- 01:44:50Or maybe we have this like monster
- 01:44:52monstrous context object,
- 01:44:55which maybe has a whole bunch
- 01:44:57of like, either it's untyped or it has a
- 01:45:00whole bunch of like
- 01:45:00nullable properties and you
- 01:45:02kinda pray that it's there.
- 01:45:04That's like all like CME principles.
- 01:45:07I'd argue this, the most principled
- 01:45:08approach about that is
- 01:45:10like having like a bag of
- 01:45:12properties that you just like lift
- 01:45:14through your function
- 01:45:15calls, but Effect gives you
- 01:45:17the best of both worlds.
- 01:45:18It gives you a very principled approach
- 01:45:20and a very convenient approach.
- 01:45:22And I think dependency
- 01:45:23injection has a kind of a bad rap.
- 01:45:26I've used it in
- 01:45:27various programming language.
- 01:45:28I've used it like a lot
- 01:45:29of in PHP in the past.
- 01:45:31I've used it like in GoLang and
- 01:45:34other programming languages.
- 01:45:35It never, it felt like, okay, this is how
- 01:45:39things should kind
- 01:45:40of, there is a solution
- 01:45:41somewhere there, but all the solutions
- 01:45:43I've used so far where
- 01:45:45it kind of like had such
- 01:45:46big foot guns that at some point I said
- 01:45:48like, okay, no, I've hurt myself too much
- 01:45:50with that.
- 01:45:51I'll do it manually.
- 01:45:53And I think Effect finally gives you the
- 01:45:55cake and lets you eat it.
- 01:45:57And I think that's
- 01:45:58really hard to explain.
- 01:46:00And I think you have to build a little
- 01:46:01thing, refactor it and
- 01:46:03like, then throw in a
- 01:46:05little bit of like type save context,
- 01:46:06which is all there is to it.
- 01:46:08Really.
- 01:46:09It's like react context,
- 01:46:10but type save and much nicer.
- 01:46:12So that's, I think something you have to
- 01:46:14try for yourself to
- 01:46:15see that how nice it is.
- 01:46:18But I agree.
- 01:46:18This is one of the best things about it.
- 01:46:20Yeah, absolutely.
- 01:46:22And why does it have a bad rep
- 01:46:24if I think
- 01:46:25about it, I think it's
- 01:46:26again, comes down to incentives.
- 01:46:28If the language makes it hard to do
- 01:46:30dependency injection,
- 01:46:32because it's never just a
- 01:46:33singular case, like, Oh, I'm going to do
- 01:46:35dependency injection on this function.
- 01:46:37And this one function will be, you know,
- 01:46:40they're written the right way.
- 01:46:41Well, you know, your program usually has
- 01:46:44a certain depth, like there's like a
- 01:46:46function and then that function calls out
- 01:46:48that of other functions.
- 01:46:49Those functions call out other functions.
- 01:46:51And then the dependency needs to travel
- 01:46:53all the way down because it's
- 01:46:54called somewhere at the leaf.
- 01:46:56For example, a database call is made
- 01:46:58somewhere at the leaf of our program and
- 01:47:01wiring through all these layers and then
- 01:47:04adding the dependency in the list of
- 01:47:07arguments all the time.
- 01:47:09Well, I'm not surprised
- 01:47:10that people get tired of it.
- 01:47:12And I started thinking about it a few
- 01:47:14weeks ago, you know, like, what are these
- 01:47:16approaches?
- 01:47:17And I started calling them just
- 01:47:19internally for myself,
- 01:47:22my own, for my own sake.
- 01:47:23Like there's this explicit dependency
- 01:47:25injection where you like to do all the
- 01:47:27wiring and like yourself.
- 01:47:29Then there's some languages like Scala,
- 01:47:31which somehow give you like some, some
- 01:47:35language features, which allow you to
- 01:47:37implicitly wire through it.
- 01:47:40You need to have a big brain for that.
- 01:47:42And it feels a little bit magical, right?
- 01:47:44This implicit dependency injection.
- 01:47:47I don't know if it's
- 01:47:47through traits or something.
- 01:47:48I'm not a big Scala user,
- 01:47:51but I did see some, some of it.
- 01:47:53And then you have Effect, which is like,
- 01:47:56it's somewhere in the middle.
- 01:47:58Like it's, it's kind of implicit, but
- 01:48:00it's also very explicit in a sense.
- 01:48:02Like you, you do declare, you see where
- 01:48:05you inject the dependency by providing
- 01:48:08the implementation.
- 01:48:09And then you also see the place where
- 01:48:11you're calling the functions and the
- 01:48:14stuff that's on the dependency because
- 01:48:17you have to yield it or yield star.
- 01:48:20So it's, it's kind of implicit because
- 01:48:22you don't have to wire it manually.
- 01:48:25You just use it at the, at the, at the
- 01:48:27site where you need it.
- 01:48:29I think it's the best of both worlds in a
- 01:48:31very similar way.
- 01:48:32How I think TypeScript is the best of
- 01:48:35both worlds where it very elegantly
- 01:48:38does type inference in
- 01:48:40most places where you can.
- 01:48:42a lot of static languages,
- 01:48:44like ask you to write type annotations
- 01:48:47everywhere, and that I think also causes
- 01:48:51like some fatigue when
- 01:48:53you use a typed language.
- 01:48:55And I think TypeScript makes it so nice
- 01:48:57that you can get away with
- 01:48:59like just type annotations in
- 01:49:00the minimum amount of places.
- 01:49:02Sometimes even for argument types, if you
- 01:49:05have a default value, for example.
- 01:49:07So most things where possible can be
- 01:49:10inferred and that's totally fine.
- 01:49:12And so think about the context, the type
- 01:49:15dependencies of an Effect of a
- 01:49:16function, think about it the same way like
- 01:49:18if it's
- 01:49:19used, it can be inferred.
- 01:49:21If you return something from a function
- 01:49:23that looks like an object with a property
- 01:49:27user, then the type can be inferred.
- 01:49:29That's because you return it.
- 01:49:31And what's so cool about Effect is
- 01:49:33like, if you use a thing in a function
- 01:49:36and using, like you said, like if you
- 01:49:39yield something, so the equivalent
- 01:49:41of like an await, then Effect and like a,
- 01:49:45on the type level wires things up
- 01:49:47nicely with TypeScript that in the type
- 01:49:50signature, you say like, aha, here
- 01:49:53we need the database client.
- 01:49:55And also during runtime makes sure,
- 01:49:58okay, there's behind the
- 01:50:00scenes, the context objects where we have
- 01:50:01the database client.
- 01:50:02So it picks it up and not just even that,
- 01:50:04but also when you finally get to run your
- 01:50:07program, it makes sure that at some point
- 01:50:10you supply your database client.
- 01:50:13And I think that is so elegant when you,
- 01:50:16when you use it, but it's, it's hard to
- 01:50:19to kind of grasp it if you, if you
- 01:50:20haven't take a look at that with
- 01:50:22code and like try to refactor a little
- 01:50:25something, but I agree.
- 01:50:26It's one of the most
- 01:50:27elegant things about Effect.
- 01:50:29Absolutely.
- 01:50:29People just have to
- 01:50:30get their hands dirty.
- 01:50:31There's no other way of learning and
- 01:50:33understanding Effect.
- 01:50:34Like obviously you could read the
- 01:50:36documentation all day long, but then
- 01:50:38you get fatigued because there's just so
- 01:50:40much that Effect provides.
- 01:50:42I often see people being very confused
- 01:50:44about what is Effect?
- 01:50:45Like, "I don't understand it.
- 01:50:47it seems to do
- 01:50:48everything", because it's such a big
- 01:50:51departure from the tiny libraries with
- 01:50:54very well-defined responsibility
- 01:50:57in the JavaScript ecosystem.
- 01:50:59And then you can like pick and choose and
- 01:51:00you can build your own tech stack,
- 01:51:03upon certain libraries, and then that's
- 01:51:05your definition of production
- 01:51:08grade software, but then
- 01:51:09you have Effect, which seems
- 01:51:10to be like the glue code.
- 01:51:12It's a really a generic
- 01:51:14programming framework
- 01:51:15Right.
- 01:51:16And I suppose in a parallel universe
- 01:51:18Effect would have been a different
- 01:51:21programming language, but I think
- 01:51:23now we sort of have the best of both
- 01:51:26worlds in that regard as well, because
- 01:51:28TypeScript is darn good.
- 01:51:30Like, and so many people
- 01:51:32already love TypeScript.
- 01:51:34I love it.
- 01:51:34It has so much structure and has so much
- 01:51:37amazing tooling around it.
- 01:51:39VS code just works super well with it.
- 01:51:41You have like LSPs that
- 01:51:43work in other places.
- 01:51:44So at this point, you need to have a very
- 01:51:47good reason to create a new
- 01:51:48program language, and I think good
- 01:51:50reasons could be superior runtime
- 01:51:53performance, what like Rust is giving you
- 01:51:56or what other program languages give you.
- 01:51:59But if you can't provide those unfair
- 01:52:02advantages, then I think you
- 01:52:03gotta stick with TypeScript for now.
- 01:52:05And TypeScript is so elegant and
- 01:52:07so flexible that you can bring all of
- 01:52:10those semantics that you would get from
- 01:52:12something like reason or a re-script.
- 01:52:15But you can bring it
- 01:52:16directly into TypeScript.
- 01:52:17This is where Effect has
- 01:52:18struck this really nice balance.
- 01:52:20But I agree you need to rewire
- 01:52:22your brain a little bit.
- 01:52:24And people maybe
- 01:52:25don't immediately get it.
- 01:52:27And I've seen an interesting correlation
- 01:52:29that people have the easiest time
- 01:52:31getting what Effect is about if they've
- 01:52:33experienced the problems that Effect
- 01:52:36solves before and they
- 01:52:39have sort of like a lot of scar tissue
- 01:52:40from trying to solve those problems
- 01:52:43themselves, like trying to do proper
- 01:52:45error handling, trying to do
- 01:52:47observability, trying to do interruption.
- 01:52:49What you've mentioned
- 01:52:50before with Kubernetes.
- 01:52:52So the more problems an engineer has
- 01:52:55experienced in the past, particularly
- 01:52:57TypeScript engineer, I feel like
- 01:52:59for them
- 01:52:59Effect clicks
- 01:53:00most quickly, but yeah, I'm curious, what
- 01:53:03was the experience talking to other
- 01:53:05engineers at Zendesk so far?
- 01:53:07What have they been confused about?
- 01:53:09What has clicked for them?
- 01:53:11So far I mostly talked through
- 01:53:13my own experience.
- 01:53:15Then I had my immediate team members and,
- 01:53:19with them, obviously it's a journey
- 01:53:21because, they have to learn it.
- 01:53:23It's also different from fp-ts.
- 01:53:25Also fp-ts, they didn't
- 01:53:27really bother learning that much.
- 01:53:29Like as long as they could kind of
- 01:53:32understand in terms of the code
- 01:53:34review, what's going on, that was
- 01:53:36already a good enough level for them,
- 01:53:38To be productive and
- 01:53:40help me with the reviews.
- 01:53:41If I write some code, also my team in the
- 01:53:46past one, two years, like we've had this
- 01:53:50unfortunate situation where
- 01:53:52we had some churn in the team.
- 01:53:53So often I was like the only backend
- 01:53:56engineer on the team while being
- 01:53:57the tech lead as well.
- 01:53:59So I really needed like my front end
- 01:54:01engineers to be able to review my
- 01:54:04code, and Effect is just doing
- 01:54:06really well in this regard as well.
- 01:54:08Because once you have the generator
- 01:54:12syntax, where you have the gen and
- 01:54:16yeld star, which you can easily map
- 01:54:19in your mind to async and
- 01:54:20await, you can build up this
- 01:54:22adapter layer, in this mental
- 01:54:24model for you once that clicks,
- 01:54:26it's very easy for them to review code.
- 01:54:30I'm not talking about stuff like,
- 01:54:32you know, database queries and, you
- 01:54:34know, how to set up proper indices for,
- 01:54:37for your table and like these backend
- 01:54:39concerns, purely backend concerns, but
- 01:54:41like all the business logic that you
- 01:54:43write on the backend and there's a ton of
- 01:54:45it, that's not an issue in terms of
- 01:54:47review.
- 01:54:48So that's sort of like the 10 second
- 01:54:50onboarding like, Hey, this stuff going
- 01:54:52to look a little bit weird.
- 01:54:53Just everywhere you see yield, think
- 01:54:55that's await everywhere.
- 01:54:57You see that gen thing, I think that's
- 01:54:59async and you should be able to like,
- 01:55:01just read that code as like your
- 01:55:03traditional async, await code go.
- 01:55:06I think that is sort of like the hail
- 01:55:08Mary 10 second onboarding
- 01:55:10where someone can get really far.
- 01:55:12Yeah, exactly.
- 01:55:13And that's like totally
- 01:55:15Pareto, like, this 20% of effort
- 01:55:19gives you 80% of the results.
- 01:55:21Like after that, obviously they're going
- 01:55:23to have questions
- 01:55:24like, what is this layer?
- 01:55:27What is this runtime?
- 01:55:29Uh, what do you do when you catch tags?
- 01:55:31What are tags?
- 01:55:32Like there will be questions like this,
- 01:55:34but they're, and yeah, they require maybe
- 01:55:38more nuanced explanations, not just
- 01:55:41like a one-to-one mapping from a
- 01:55:43new concept to a well-known
- 01:55:45well-established other concept.
- 01:55:47But, but it's that
- 01:55:4920% of the, of, of the productivity
- 01:55:53that you're achieving
- 01:55:54with the 80% of the effort.
- 01:55:56So already with the 10 second onboarding,
- 01:55:58you're so far ahead that the
- 01:56:00reviews just work already.
- 01:56:02And then I like this idea of like,
- 01:56:04exposing someone
- 01:56:06to Effect first through
- 01:56:07like reading
- 01:56:07code and doing code review.
- 01:56:09Since this is where someone through
- 01:56:11the context that they are already
- 01:56:13familiar with, maybe through a refactor,
- 01:56:15maybe through a new feature, they
- 01:56:18have all of the context that they need to
- 01:56:20understand what the problem is about.
- 01:56:22And now they can focus
- 01:56:23on the implementation.
- 01:56:24And I think what's also so nice is
- 01:56:26depending on where someone
- 01:56:28reviews the code, possibly ideally in
- 01:56:30their IDE, this is where you can also
- 01:56:33use all of like the type inference
- 01:56:35benefits to help you understand
- 01:56:38what's going on, if you hover over an
- 01:56:40effect and see like, Oh, this is where
- 01:56:43we can have an error that is about maybe
- 01:56:46the user wasn't found or maybe
- 01:56:50another service is done.
- 01:56:52This can add so much to the picture to
- 01:56:54understand what's going on.
- 01:56:56Where before everything was just like,
- 01:56:58an implicit sort of wake
- 01:57:01thought, and I feel like this is where
- 01:57:03someone just by also being exposed
- 01:57:06can pick up so much.
- 01:57:08And then you have seen at the end of the
- 01:57:10day, a lot of code users are
- 01:57:13very similar to each other.
- 01:57:15And this is where in someone get now
- 01:57:17takes that step to writing their own
- 01:57:19Effect code, they probably have already
- 01:57:21seen two or three places that are very
- 01:57:23similar, so you can go copy some of that
- 01:57:26code, go over there, adjust it, and
- 01:57:29bring the usual programming muscle.
- 01:57:31And it's works going to work just as well
- 01:57:34and probably even better
- 01:57:35since you have improved type safety.
- 01:57:37Yeah, absolutely.
- 01:57:39Also, I really love the way you can work
- 01:57:42with generators because anything
- 01:57:44that's within the function body of a
- 01:57:47generator, it's basically your happy
- 01:57:49path because all the error cases just
- 01:57:52short circuit the happy path.
- 01:57:54And then you just do a quick pipe after
- 01:57:56the Effect where you
- 01:57:57handle all the
- 01:57:58possible failure cases.
- 01:58:00And I don't know why, but I just love
- 01:58:03this style of writing programs.
- 01:58:06Here's my happy path.
- 01:58:07Everybody can understand what's going on.
- 01:58:10And then now in this pipe, I'm going to
- 01:58:13handle all the errors.
- 01:58:14Right.
- 01:58:15This way can like, sprinkle a little bit
- 01:58:16of like extra sauce on top of it, where
- 01:58:19you can, I often do
- 01:58:20also like timeouts there.
- 01:58:22I add a little bit of like Otel
- 01:58:24instrumentation around that, or maybe do
- 01:58:27like a retry for an error
- 01:58:29but yeah, as you say,
- 01:58:31like in the generator,
- 01:58:32this, and I think this is so beautiful
- 01:58:34about it is like, you can nicely separate
- 01:58:36sort of like signal from the other stuff
- 01:58:39and say like, okay, here's my business
- 01:58:41logic and here's like,
- 01:58:43here are those other concerns.
- 01:58:45I think like in the future, if we have
- 01:58:47like a next
- 01:58:48generation of IDEs, et cetera,
- 01:58:50and maybe like even more AI assisted,
- 01:58:53maybe that can help you and say like,
- 01:58:55Hey, hide everything that is not about
- 01:58:57the business logic or
- 01:58:59hide everything that,
- 01:59:00or like highlight everything that is
- 01:59:02about concurrency or highlight everything
- 01:59:04that is about error handling with Effect.
- 01:59:06You already put in sort of like the
- 01:59:08structural effort and I think we're going
- 01:59:11to see some, some big rewards even beyond
- 01:59:13what we have right now.
- 01:59:16That's very interesting.
- 01:59:16I never thought about this, but, uh, it
- 01:59:19makes it enough sense.
- 01:59:20Yeah.
- 01:59:21The, the tooling that you can build on,
- 01:59:23on, on top of these like static
- 01:59:25descriptions of a
- 01:59:26program is just like limitless.
- 01:59:28Yeah.
- 01:59:29Interesting.
- 01:59:30Yeah.
- 01:59:30This is something I'm
- 01:59:31very, very excited about.
- 01:59:33And we've, we talked briefly before about
- 01:59:35the launch of the Effect Playground.
- 01:59:37I think it's super nice to have like an
- 01:59:39environment where it can just play
- 01:59:41around a little bit, get
- 01:59:42familiar with something.
- 01:59:43I use it on a daily basis to maybe
- 01:59:45understand an API surface a bit better
- 01:59:48and just play around with it, have fun.
- 01:59:50And we also threw in support for some of
- 01:59:53the effect dev tools in there,
- 01:59:55notably also the trace viewer.
- 01:59:59And this is where you can get real time
- 02:00:01feedback for what does it mean for
- 02:00:03my program to run this is where it may be
- 02:00:05a certain thing took like a second
- 02:00:08and then should just time out, et
- 02:00:11cetera, like visually
- 02:00:12see what's going on.
- 02:00:14There's so many tooling possibilities
- 02:00:16that are coming.
- 02:00:18And that's gonna just kind of like the
- 02:00:20gift that keeps on giving as like
- 02:00:22you adopt Effect, and there's like so
- 02:00:23many benefits that just fall out of that.
- 02:00:26I think we're still at the beginning and
- 02:00:28it's already very rewarding for at
- 02:00:31least in my experience
- 02:00:32and what I've seen so far.
- 02:00:33So you shared your
- 02:00:35experience using an adopting Effect
- 02:00:38and also how you help your own team adopt
- 02:00:42Effect and be productive with it
- 02:00:44through code reviews and helping them to
- 02:00:46refactor code and build new Effect
- 02:00:48programs.
- 02:00:49But given that you built this service
- 02:00:51framework that is used, I think all
- 02:00:53across Zendesk when it comes to
- 02:00:55TypeScript code, there's now more and more
- 02:00:58people that are exposed to effect.
- 02:01:00So how was their experience?
- 02:01:02Maybe you got a little
- 02:01:03bit of like questions.
- 02:01:05What is that thing?
- 02:01:06Uh, maybe some similar concerns that
- 02:01:10people asked about fp-ts
- 02:01:13So which sort of questions did you hear.
- 02:01:16Yes.
- 02:01:16Uh, well, that's a great question.
- 02:01:18So let me start with another
- 02:01:20team, uh, not my team.
- 02:01:21That's the closest to our team.
- 02:01:24And they have some services that are
- 02:01:27fully written in fp-ts
- 02:01:28and using our service
- 02:01:30framework, so they're looking and
- 02:01:33watching us from the
- 02:01:34sidelines, writing Effect
- 02:01:36code line, because we're enjoying this
- 02:01:38opportunity of building a completely
- 02:01:40new service from scratch.
- 02:01:42And, uh, they're, they weren't so lucky.
- 02:01:43So they're still stuck
- 02:01:44with their fp-ts project.
- 02:01:46And they're just looking at us, uh,
- 02:01:50and are maybe a little bit jealous,
- 02:01:53of us that we're writing effect
- 02:01:55already because they've been looking
- 02:01:56forward to writing effect as well.
- 02:01:59But, but I'm helping them try to
- 02:02:01figure out how to migrate, fp-ts to
- 02:02:04effect also incrementally
- 02:02:05it's, it's a bit tough.
- 02:02:07Especially if you have your own
- 02:02:08abstractions and own ways of doing things
- 02:02:12with fp-ts, so it's really slow.
- 02:02:15And also it's really hard to justify, to
- 02:02:17spend the time to fully migrate a
- 02:02:20rather large project in one go.
- 02:02:23So it really has to be incremental.
- 02:02:25So that's, that's a
- 02:02:26positive feedback from them.
- 02:02:27But then we also have teams that are
- 02:02:30outside of our immediate organization
- 02:02:33and they are, let's say more TypeScript
- 02:02:36native teams and they have completely
- 02:02:40different requirements from, from my team
- 02:02:44and from the other Guide team.
- 02:02:46Because Effect was not their choice.
- 02:02:49It was our choice for, for the
- 02:02:51TypeScript service framework.
- 02:02:52Right.
- 02:02:53And the service framework does
- 02:02:55provide a lot of value, but without
- 02:02:58knowing Effect necessarily or fp-ts
- 02:03:01even it's really hard to tap into
- 02:03:04that value and, and use it immediately in
- 02:03:06your project, which knows nothing
- 02:03:08about fp-ts or Effect and the engineers
- 02:03:10know nothing about fp-ts and Effect.
- 02:03:12So here Effect actually brings some
- 02:03:15really good tools, that can
- 02:03:17help bridge between the two
- 02:03:20requirements and
- 02:03:21that's the adapter layers.
- 02:03:24So basically when you have an Effect, you
- 02:03:25can run it as a promise or you have
- 02:03:28a promise and then you can wrap it into
- 02:03:29an effect using different APIs.
- 02:03:32So in our service framework, this is
- 02:03:35something that we're going to be leaning
- 02:03:37on more and more because we want to
- 02:03:41provide the benefit to all the users
- 02:03:44regardless whether
- 02:03:45they choose effect or not.
- 02:03:47So for every effect API, we can have a
- 02:03:49rule that we will also be able to a
- 02:03:51promise based API, which is fully built
- 02:03:54on top of the effect, because we're just
- 02:03:56going to satisfy all the dependencies at
- 02:03:58the time and, and run it as a promise.
- 02:04:02And then they can always look up what
- 02:04:04kind of failure
- 02:04:05modes there can be because they can just
- 02:04:07follow by convention, or by
- 02:04:10inspecting the implementation.
- 02:04:12They can see which effect APIs,
- 02:04:14rather which service framework effect
- 02:04:16based service framework API is wrapped
- 02:04:18and then discover the
- 02:04:20type signature there.
- 02:04:22So that's, that's one way how they can
- 02:04:24reap the benefit of knowing
- 02:04:25what kind of errors there are.
- 02:04:26They don't have to
- 02:04:27inspect all the depths.
- 02:04:30I don't know how even people were doing
- 02:04:32it with like regular
- 02:04:33type script libraries.
- 02:04:34You know, how do you discover what
- 02:04:35kind of errors you may encounter?
- 02:04:37Like, I think typically you don't and you
- 02:04:39discovered during runtime and logging.
- 02:04:42Yeah, exactly.
- 02:04:44It will be so nice to know like, Oh,
- 02:04:46here's the documentation page.
- 02:04:48It lists all the 150 ways of my program
- 02:04:52failing or my library failing.
- 02:04:54But this, this doesn't exist.
- 02:04:56I at least I have not seen a library
- 02:04:59documenting their
- 02:05:01implementation or
- 02:05:02their API's to this level.
- 02:05:04It would also be really terrible to
- 02:05:05maintain the documentation for this.
- 02:05:07I mean, we have the perfect primitive for
- 02:05:09that, which are types and I
- 02:05:11guess more modern programming languages,
- 02:05:14such as Rust, et cetera, they have
- 02:05:16figured this out and they return results
- 02:05:19in case something can go wrong.
- 02:05:21And I mean, Effect is about the same idea
- 02:05:24that you don't just return
- 02:05:26just the success value, but also you're
- 02:05:29returning the, the errors just through
- 02:05:31the return channel as, as other things as
- 02:05:34well, but coming back to
- 02:05:35the point you were just making, I liked
- 02:05:37that approach that basically for
- 02:05:39the folks in your organization who are
- 02:05:43already excited and interested about
- 02:05:45Effect, they can already start consuming
- 02:05:48the effect API's for the ones who
- 02:05:50are still on the fence or are not quite
- 02:05:53ready to make the jump yet.
- 02:05:55They can still stay in the Promise land
- 02:05:58and need to deal with,
- 02:06:01errors, et cetera, the, the good, bad
- 02:06:03way, um, the old bad way.
- 02:06:07Which sort of questions do you typically
- 02:06:09hear when someone is as
- 02:06:11confronted with Effect, I suppose
- 02:06:14there's a full spectrum of people.
- 02:06:16You immediately get it and are excited to
- 02:06:19dig in to people who are maybe curious,
- 02:06:23but don't quite get it.
- 02:06:25And then maybe people who are much
- 02:06:27more skeptical and maybe this
- 02:06:30reminds them of like some other bad time
- 02:06:32they had in the past and why they have
- 02:06:35reasons in mind, why
- 02:06:36they don't want to adopt it.
- 02:06:37So tell me more about the different kinds
- 02:06:39of reactions that you've seen.
- 02:06:42Yes.
- 02:06:43So I've done a few
- 02:06:46Effect related presentations
- 02:06:48at Zendesk already.
- 02:06:49I presented at our annual tech
- 02:06:52conference in May.
- 02:06:54So I had the opportunity to actually
- 02:06:56get some of those questions and lots
- 02:07:01of people are actually skeptical.
- 02:07:03Maybe due to their own
- 02:07:05experience with something
- 02:07:06similar that they tried or
- 02:07:07just, it just looks too functional for
- 02:07:10them and they're more familiar in the
- 02:07:14OP and dynamically typed languages.
- 02:07:18They don't necessarily understand it.
- 02:07:21Like at Zendesk, we have lots of
- 02:07:23engineers who have experienced all
- 02:07:25the issues related to scale
- 02:07:27maintainability,
- 02:07:29testability, reliability,
- 02:07:30all these things, but still this alone is
- 02:07:35not necessarily
- 02:07:36not a huge selling point for them necessarily
- 02:07:38because they already
- 02:07:39have their ways around it.
- 02:07:41Like they have years of experience doing
- 02:07:43Ruby years of experience doing whatever.
- 02:07:45And they, they know their way around it.
- 02:07:48Maybe they don't even care necessarily
- 02:07:49about super reliability because
- 02:07:52there's like feature flex.
- 02:07:54So you can basically not break
- 02:07:55everybody at the same time, but you just
- 02:07:57break a tiny bit of, uh, of the
- 02:08:01customers, which is understandable.
- 02:08:04If you don't have any other option
- 02:08:07because you're limiting the blast radius.
- 02:08:10But it's also not something I'm
- 02:08:11really a big fan of.
- 02:08:13Like I really want to catch the errors
- 02:08:16and possible failure cases even
- 02:08:18before I commit my changes.
- 02:08:20Like that's the ideal thing.
- 02:08:21I don't even want to push it somewhere to
- 02:08:23a CI and then waste CPU cycles,
- 02:08:26of a CI just to make it fail.
- 02:08:29Um, and then repeat rinse and repeat many
- 02:08:32times possibly, because also sometimes
- 02:08:34it's really hard to run all the things
- 02:08:36that the CI runs locally due to different
- 02:08:39limitations, but yeah, so we have these
- 02:08:42people who know their way around.
- 02:08:44So for them, maybe a bigger concern is
- 02:08:47usually, okay, but
- 02:08:48listen, we have so many
- 02:08:50different technologies at Zendesk, we have
- 02:08:53to consolidate like, why should this be
- 02:08:56the thing that we consolidate on?
- 02:08:58How will you align with
- 02:08:59all these hundreds of engineers
- 02:09:02on the single one technology?
- 02:09:03Obviously we have some processes like
- 02:09:05ADRs and whatnot, but if it comes
- 02:09:09to a big change like this, obviously
- 02:09:12there's going to be also resistance
- 02:09:13because people just are accustomed to
- 02:09:15to the status quo.
- 02:09:18And they're their way of operating and
- 02:09:21they don't necessarily want to switch.
- 02:09:23Which is totally reasonable.
- 02:09:25And I don't want to change anybody's
- 02:09:28mind or I don't want to force
- 02:09:31anybody to now, you know, forget about
- 02:09:34promise land and
- 02:09:35start incorporating
- 02:09:37Effect into your code
- 02:09:38base starting tomorrow.
- 02:09:40I truly believe it should be like a
- 02:09:43choice that everybody
- 02:09:45can make for themselves.
- 02:09:47But then you have, you know, the company
- 02:09:49incentives to try and consolidate to,
- 02:09:52to not go into too many directions
- 02:09:54because if you want to be productive at,
- 02:09:57at the top level, you know, at an
- 02:09:59organizational level, like the more
- 02:10:02people pull in the same direction, the
- 02:10:05better you are and the more productive
- 02:10:08you are.
- 02:10:09So these are also a little bit
- 02:10:10political, uh, you know, influence
- 02:10:13and political, it's a
- 02:10:16question of politics as well.
- 02:10:17Like how can you influence
- 02:10:18without being in a big leadership
- 02:10:22position and stuff like that.
- 02:10:24Have you found some arguments like from
- 02:10:26the many things that Effects can offer
- 02:10:28that has resonated still with the people
- 02:10:32who are more in the skeptical spectrum?
- 02:10:34Yes.
- 02:10:35Um, so sometimes I do, because let's say
- 02:10:39you're a company and then now you
- 02:10:42had this financial crisis where the
- 02:10:44interest rates went up and now, uh, you
- 02:10:48figure out that money doesn't grow on the
- 02:10:50trees and you have layoffs and whatnot.
- 02:10:53And suddenly you stop backfilling for
- 02:10:56positions, you know, which, which
- 02:11:00came up because of churn
- 02:11:01and you're not used to pairing.
- 02:11:04So you have hiring
- 02:11:04freeze or whatever suddenly.
- 02:11:06And, but the expectations of productivity
- 02:11:08are staying the same.
- 02:11:09So basically you have
- 02:11:10more workload per person.
- 02:11:13That's, that's the final result.
- 02:11:15The company still expects you to deliver,
- 02:11:17but now you are fewer people to do so.
- 02:11:20It's, it's a hypothetical one.
- 02:11:22Right.
- 02:11:22So what do you do?
- 02:11:25Well, I think TypeScript is positioned
- 02:11:27really well because
- 02:11:28you can have TypeScript
- 02:11:30both on the front end, which in many
- 02:11:32cases you do, and then
- 02:11:34you can have it on the
- 02:11:34back end as well, which
- 02:11:35is, isn't a terrible option.
- 02:11:37Especially like, you know, you have NodeJS
- 02:11:40or Dino or whatever, nodeJS with
- 02:11:42its event loop runtime, perfectly suited
- 02:11:46for i/o heavy operations.
- 02:11:50And as far as I'm aware, like 90% of what
- 02:11:53Zendesk does is i/o heavy.
- 02:11:55We take a message, no matter where it
- 02:11:57comes from, we do some processing and
- 02:12:00we send a message somewhere else.
- 02:12:02Like maybe it's like you, you, you start
- 02:12:05a record in the database or you emit a
- 02:12:07thing in Kafka, maybe you have like a
- 02:12:09MySQL connector with Kafka, so you can
- 02:12:11do these things
- 02:12:13in a single transaction.
- 02:12:14So basically you manage your distributed
- 02:12:16transactions this way.
- 02:12:17So you do a ton of like taking things
- 02:12:20from here, pushing there.
- 02:12:22A lot of waiting time, a
- 02:12:23lot of i/o, what do you do?
- 02:12:25Like with Ruby, obviously.
- 02:12:27And this is another thing
- 02:12:28that I often mention is cost.
- 02:12:30Like if you have nodeJS handling
- 02:12:34traffic, like large concurrent
- 02:12:37traffic, heavy traffic, you can save a
- 02:12:40lot of cost because with Ruby.
- 02:12:44What's your option there?
- 02:12:45Well, yes, you can use threads, but then
- 02:12:48your memory consumption goes up because
- 02:12:50threats are not for free.
- 02:12:52Or you can scale horizontally.
- 02:12:54So when you put the horizontal pod
- 02:12:56autoscaler max it out at 24 replicas
- 02:12:59or whatever you figure out the rules
- 02:13:02around how to increase the
- 02:13:04replica count by how much, when, what is
- 02:13:06the signal that you're looking at?
- 02:13:08You know, you can figure out all of these
- 02:13:10things, or you can
- 02:13:12just have a few replicas,
- 02:13:14maybe one per availability zone, 2
- 02:13:17per availability zone for extra
- 02:13:19redundancy
- 02:13:20of a node, uh, process.
- 02:13:22And then suddenly you
- 02:13:22have a throughput of what?
- 02:13:24Tens of thousands of requests per second.
- 02:13:27So, so it's also money, you know?
- 02:13:30So when you, when you talk to high, uh,
- 02:13:32to the leadership, you have to
- 02:13:35convince them with some
- 02:13:36hard hitting facts.
- 02:13:38And it's not just, obviously you can say,
- 02:13:40ah, in theory, this works.
- 02:13:43No, you have to sit down, do the
- 02:13:45analysis, maybe set up
- 02:13:46some project which can
- 02:13:48demonstrate how much more cost
- 02:13:51efficient it is compared to other similar
- 02:13:54workloads, put it into
- 02:13:56money, uh, values, right?
- 02:14:00Uh, convert it into dollars or whatever,
- 02:14:02and then show the difference.
- 02:14:05And then once you do this, you know, you,
- 02:14:08you, you won the golden ticket or
- 02:14:10something because it comes down to
- 02:14:12money in the end always.
- 02:14:13Yeah, totally.
- 02:14:15And I agree with that approach that
- 02:14:18you can basically like, let the
- 02:14:20actions, actions speak louder than words.
- 02:14:22And you're doing
- 02:14:24the right work already.
- 02:14:26You're are shipping things in production.
- 02:14:29You're appreciating and leveraging all
- 02:14:32the benefits that
- 02:14:34Effect provides to you.
- 02:14:35And I think the, your team and some other
- 02:14:39peer teams have a great
- 02:14:41experience already with Effect.
- 02:14:42And I think those will show the results
- 02:14:46and that might make a case for itself
- 02:14:49and prove out that it's not just words,
- 02:14:52but it's actually an improved
- 02:14:54reality that makes teams more effective,
- 02:14:58more efficient, happier, and
- 02:15:00possibly also then saves resources and
- 02:15:04money when it comes to running those
- 02:15:06services,
- 02:15:07saves down times, et cetera.
- 02:15:09So I'm sure the, the more time continues,
- 02:15:13the more all of those arguments
- 02:15:15going to resolve
- 02:15:16themselves in your favor.
- 02:15:18And I applaud you for being
- 02:15:20on the early adopter train.
- 02:15:24Thank you.
- 02:15:24I, I do hope that it
- 02:15:26plays out really well.
- 02:15:28I'll do my part for sure.
- 02:15:30Perfect.
- 02:15:31So maybe that leads me to the last
- 02:15:34question that I'd love to hear your
- 02:15:36thoughts on, which is what gets you most
- 02:15:38excited about the future with Effect.
- 02:15:43Yes.
- 02:15:44Ah, that's a good question.
- 02:15:47I haven't put a lot of research into
- 02:15:51Effect Cluster, but it's definitely
- 02:15:53something I'm observing again from the
- 02:15:56sidelines and look forward to using
- 02:15:58in the future, maybe for some
- 02:16:00use cases like backfills, let's say.
- 02:16:04I have my event sourced service and now I
- 02:16:07evolve my, uh, event schema from version
- 02:16:11one to version two,
- 02:16:12maybe two version three.
- 02:16:14And now I feel like, okay, my switch
- 02:16:18statements where we, where I, where I
- 02:16:20switch between the versions of the schema
- 02:16:22and then, uh, the way I'm reducing the
- 02:16:25events into a single aggregate, it's
- 02:16:28getting a bit cumbersome.
- 02:16:29So let's just migrate some of those old
- 02:16:31schema versions to the latest one.
- 02:16:34So having like millions, maybe billions
- 02:16:37of records, it could take quite
- 02:16:40some time to do this sequentially.
- 02:16:43So having like a solution where I can
- 02:16:45have set up some workers, which can agree
- 02:16:48on, you know, the scheduling and how
- 02:16:50they're going to partition the database
- 02:16:52table among each other, uh, and do it in
- 02:16:56parallel, that, that would be just the.
- 02:16:59You know, perfect dream come true.
- 02:17:01I don't want to start the backfill in
- 02:17:03every cluster one after another, or even
- 02:17:06in parallel, and then like having to like
- 02:17:08watch tens or dozens of, you
- 02:17:12know, monitors to see the progress of
- 02:17:14each individual
- 02:17:15backfill on every Kubernetes
- 02:17:17cluster and then managing that for hours.
- 02:17:22You know, if that could be like maybe a
- 02:17:2410 or 20 minute thing, that would be
- 02:17:28just the perfect dream, right?
- 02:17:29So I'm looking forward to Cluster.
- 02:17:32Yeah, me too.
- 02:17:33This is, uh, one of the, as I said, like,
- 02:17:35uh, be the, the gift that keeps on giving
- 02:17:38and we're going to have like many layers
- 02:17:41built on top of the foundations that
- 02:17:43we already benefit from and the Effect
- 02:17:47Cluster and Effect workflow primitives
- 02:17:49that are in the work and the
- 02:17:50systems that are in the work.
- 02:17:52Uh, I think that's gonna, yeah, that
- 02:17:54that's going to be literally next level.
- 02:17:56This is going to unlock some benefits
- 02:17:59that you see from systems like Temporal
- 02:18:02Temporal IO, not the new time standard,
- 02:18:05but temporal IO, which is about durable
- 02:18:07workflows and, and workflow scheduling
- 02:18:09and running long lived things.
- 02:18:13You can already do that in Effect
- 02:18:15combined with temporal, but Effect
- 02:18:19is the perfect foundation to do that, uh,
- 02:18:21natively with the effect primitives.
- 02:18:24When you think about rerunning something,
- 02:18:27if something has failed scheduling, some
- 02:18:29work, um, processing work across multiple
- 02:18:33workers and massively
- 02:18:35parallelized systems.
- 02:18:37This is where we have like amazing
- 02:18:39foundations for that.
- 02:18:41And that's being systematized with the
- 02:18:43effect cluster and effect workflows
- 02:18:45project, which is now
- 02:18:46in development for, I think also like in
- 02:18:49research for a few years now.
- 02:18:51And I think it's alpha grade right now.
- 02:18:54I think some people are
- 02:18:55already starting to use it.
- 02:18:57I'm actually also planning to give it a
- 02:19:00shot soon for the music app that I'm
- 02:19:03building, and I think it will take a
- 02:19:05little bit of more time to be fully
- 02:19:07production ready, just because it's also
- 02:19:08a very ambitious project, but it's very
- 02:19:11principled and I'm very
- 02:19:12excited about the potential for it.
- 02:19:15And I think we're going to hear a lot
- 02:19:16more about that in the months and years
- 02:19:19to come and possibly the next year's
- 02:19:21Effect Conference already.
- 02:19:23So yeah, super excited that
- 02:19:25you're excited about that.
- 02:19:27Because I think you have some really
- 02:19:28interesting use cases for that.
- 02:19:30So, Attila, thank you so much for
- 02:19:33taking the time today to doing the
- 02:19:35initial episode of the Cause & Effect
- 02:19:38Podcast with me and taking the time.
- 02:19:41So that's much appreciated.
- 02:19:42And thank you so much.
- 02:19:44Thank you.
- 02:19:44It's been a great honor to be the first
- 02:19:46guest of this amazing podcast.
- 02:19:50Perfect.
- 02:19:50Thank you.
- 02:19:51Take care.
- 02:19:52Take care.
- 02:19:53Thank you for listening to
- 02:19:54the "Cause & Effect" podcast.
- 02:19:56If you've enjoyed this episode, please
- 02:19:57subscribe, leave a review,
- 02:19:59and share it with your friends.
- 02:20:01If you haven't done so already, you can
- 02:20:03join our Discord community.
- 02:20:04And if you have any questions, feedback,
- 02:20:06or suggestions about this episode or
- 02:20:09about Effect in general,
- 02:20:10don't hesitate to get in touch.
- 02:20:13See you in the next episode.