My reasons are:
- I don't need to share type definitions between the frontend and backend; the frontend can generate TS type defs using GraphQL introspection regardless of which language the backend is implemented in.
- The backend is doing a lot of data manipulation, which TS is not very good at. For example, there's no built-in group-by function, and group keys must be primitives since TS doesn't have value equality for objects or arrays.
- Static typing doesn't help much with setting up GraphQL resolvers correctly, and overall feels much less useful than on the frontend where it's absolutely stellar to type check all GraphQL queries, React calls, 3rd party component props, and so on.
- I miss clojure.spec for validating calls to external services.
Plus a few more situational reasons:
- I work in a team that's already familiar with Clojure. I don't think it's a huge barrier to hiring either; I didn't know Clojure before I joined, they just recommended me a book.
- I personally don't find that using the same language everywhere helps much in reducing context switching costs. Using different languages actually feels more engaging, especially when one is as pleasant as Clojure.
Put all these together and I'm seeing real benefits in using different languages.