Hacker News new | ask | show | jobs
by throwitaway222 848 days ago
I bought into the "RX Java/JS/etc.." years back. Everyone I showed the code couldn't handle it, and we just backed off to other methods, and things worked just fine.

RX has some interesting ideas, but from a practical standpoint, at companies not netflix, it just doesn't work

5 comments

Even at Netflix RxJava is not fully accepted. When I was there I wrote a service which called many downstreams. It orchestrated test user creation. I used RxJava because it was being pushed by the platform team, and coupled well with our internal GRPC api handlers.

I shared with the team and people complained about the complexity… so I ended up ripping it out. What people wanted was a test user creation service that worked well and could be maintained… not one that was the most efficient.

Looking back, do you think choosing practical reasons over efficiency was the right call?
Yes. Code is read (and debugged) way more than it is written.

I was using RxJava initially because it was being pushed by the platform team and coupled pretty well with the GRPC interfaces we used internally. However, the rest of my team couldn't/didn't want to wrap their minds around the concurrently functional tasking that it brought (which was understandable).

I didn't want the code to have a bus factor of 1 (me).

Is there any reason they don't adopt kotlin? It seems a lot simpeler with suspended functions and coroutines?Instead of RXJava.
In growth we had a failed experience with groovy… but Netflix wide? I think they just wanted to stick with basic Java.
Adopting RxJava means fixing all the bugs in everything up front. That is why it feels complex. In my opinion and in the opinion of other adopters, it is a more expressive way to define correct behavior.

This is essentially the same tension between static and dynamic typing.

No matter what, all bug free code is complex. Correct code can be written in any paradigm.

But productful code ships with bugs.

Does test user creation need to be bug free? I don’t know. It feels like something where productful test user creation can ship with bugs, even if in reality your test code harnesses should not be buggy.

You can step even further back and ask: when you have essentially unlimited resources, why ship buggy code at all? Netflix has unlimited capital, and it isn’t in a hurry anywhere. Engineers should never choose productful over bug-free. You learn nothing (Netflix’s product problem will never resemble your startup’s product problem) and you forfeit the opportunity to learn (ReactiveX is a good, expressive paradigm).

This is a startup forum, is this true for startups? IMO, yes. Your startup is going to fail. You will not learn valuable product lessons from the journey. I mean people certainly pretend and say they do, but even in the situation of success, Brian Chesky still hasn’t become Walt Disney last I checked. But once you have enough money to be employed for a year, as an engineer, you know, fucking learn how to do something the right way, bug free and performantly.

So I agree your coworkers are fundamentally making an error.

> Adopting RxJava means fixing all the bugs in everything up front. That is why it feels complex.

I disagree with this. It mentally changes the thought processes when debugging, which was the biggest issue that was brought up.

> Does test user creation need to be bug free? I don’t know. It feels like something where productful test user creation can ship with bugs, even if in reality your test code harnesses should not be buggy.

It should be bug free at Netflix scale. My service created more customers daily than Netflix signed up monthly. It also sat in the middle of Growth. People use it to gate deployments. It needs to work flawlessly (or at least consistently).

This was part of some “testing in production” type scheme?

Are there any talks or blog posts on how y’all wired this up, lessons learned etc?

No this all happened in preprod. Every team in the growth space ran their own tests across the various permutations of users (country, payment type, plan, ... at the time free trial, feature flags) to determine if their code was valid and worked to go to production. Each team continuously deployed independently. Given that we also were continuously integrating as well... you get a lot of customers created.

Sorry no talks.

I tried using an API based on RxJava to implement some async code... It was buggy as hell, as using the API correctly was nearly impossible for me - that's the opposite of a good API which makes it very hard to use wrong. I am in the process of replacing all that shitty code with Virtual Threads, and all bugs just immediately disappear as the code is so much more straightforward to analyse.
I had a close look at RxJava and decided I wasn't smart enough to understand it. I intentionally didn't tell my colleagues about it, they would have loved it and I would have been in big trouble.
Yeah, I'm in the same boat. I'm coming fresh to the team and I haven't written any Java in anger for 8 years, and there's Rx in here. I'm sure I could sit here and study it over and over until I get it, but why? My service is running at <10 QPS. I cannot believe the runtime value is worth the SWE onboarding time.

Promises are all over the place too. I understand why someone thought this was a good idea ("I'm doing the scalable thing!"), but in the end it appears completely unnecessary (e.g. doing a blocking get call in all uses).

The problem with Java isn't Java. The problem with Java is that it lets so many people hold it wrong, and the Java ecosystem encourages it.

Yeah the problem with Java and a language like Kotlin is it has so many language features. Meaning programmers can do lots of hard to understand things.

I've been coding in C recently and really enjoy the limitations. Usually there's only one way to do something.

We use RxJS in two of our video streaming products. In one of them we have a spaghetti bowl of streams. You can follow most of what’s going on, but not 100%. And it hurts. Architecture, patterns and naming conventions hamper readability and understanding a lot.

In the second codebase, things are a bit simpler. The architecture allows for more readable code and far fewer cases where multiple streams might introduce loops or race conditions due to being in separate files and initialised at different times. We felt the benefits of a v2 build ;-)

I’d say RxJS is a great tool to help respond to multiple concurrent data streams (e.g. user interactions happening at the same time as video playback). If you’re not dealing with a lot of realtime behaviour, you probably don’t need it.

In my opinion the complexity ramps up massively if some consumers want a reactive streams pushing data to them and other consumers prefer to request a current static value of the same data. Watch for this and experiment to find comfortable solutions or acceptable compromises.

If you think you need RxJS, take a look at Redux + Sagas and consider a choice between the two. I prefer the rigour and dev tools for Redux + Sagas over the freedom to be hairy with Rx. But observable streams are a lovely abstraction.

RX definitely requires some non-standard thinking to do well, but any competent engineer can get it if they want to dedicate the time to it.

But you're right, the same things can be accomplished in other ways with less up front effort. But where it really shines is when you hit massive scale. Having RX and its concepts in place ahead of growth makes the growth easier.

I think this is where things go wrong. I used RxJS plenty and tried even spearheading its usage at times in some of our apps since it could cleanly solve some problems in what I thought were elegant solutions. I quickly abandoned this after realizing that the upfront ask in terms of dedicating time to learning it for some people is just too much for them to handle.

I'd say a decent chunk of engineers just were not competent enough to get it in the first place and then there were those who just refused to put in the time to learn.

i.e. there are many engineers who I truly believe do not even want to put in the effort to be competent in the first place. That or false competence takes precedent as well.

If you're doing worker threads with multiple callbacks to listeners whose lifecycles are properly managed to avoid memory leaks then Rx will probably be simpler. If you're not doing threading or if your listeners only receive one callback then Rx might be overkill.