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