in the recent migration project of a legacy API gateway that is now in production. The new API gateway is built on Deno, NestJS, and Effect. In this talk, I am going to Give an overview of Effect. Share the motivations, results, and key takeaways for adopting Effect in the project. 4 4
has just reached the stable release (v3) in April 2024 [1]. In theory, it provides the Effect System [2], one of the research topics in computer science [3]. In practice, it enables to build typed, robust, and scalable applications. It also provides standard-library like features such as Either type, Immutable Data Structures, Pattern Matching, etc. 7 7
Error, Requirements> . From its type, you can think of it as a “smart Promise” that can explain both the success and error types. You can create effects From functions: Effect.sync , Effect.tryPromise , Effect.gen From the other values: Effect.succeed , Effect.fail 9 9
pipe or yield* , which is similar to then and await in Promise. However, you must explicitly run effects using the following methods, which is different from Promise. Effect.run(Sync|Promise) returns a value or throws an error. Effect.run(Sync|Promise)Exit returns a value or an error. 10 10
result from I/O operations in the API gateway, I decided to use Effect. Robustness and Scalability The naive implementation is easy to maintain, but not very robust or scalable. Code maintainability Efforts to improve robustness and scalability result in less maintainability of the codebase. 13 13
whole codebase and decided to use it only in certain parts (e.g. Guard in NestJS). This was because the project members were giving negative feedback: “Difficult to read and write”. I did not expect that introducing the piping style would be as difficult as understanding the Effect concept. The Effect contributors understand these difficulties so well that they have done a lot of work around them. 23 23
x = await Promise.resolve(1); const y = await Promise.resolve(2); return x + y; }; // function*/yield* const add = Effect.gen(function* () { const x = yield* Effect.succeed(1); const y = yield* Effect.succeed(2); return x + y; }); Generators bring the same mental model as async/await 25 25
for building a typed, robust, and scalable application in TypeScript. I adopted it to solve the trade-off between “robustness and scalability” and “code maintainability” in the recent project. I ended up using it only in the certain parts because introducing the piping style was also difficult for the project members. I am sure that Effect will get better because the contributors have done a lot of work around this difficulty. 28 28