Erlang: The coding language that finance forgot (2022)
efinancialcareers.com
efinancialcareers.com
The BEAM is the brainchild of the excellent engineers at Ericsson, the product of decades of R&D into building performant, scalable and reliable software for their telephony products.
It scales like a dream, runs your application on all available cores with no trouble at all, handles massive amounts of concurrent requests without breaking a sweat. The programming techniques it enables with projects like Phoenix LiveView are unique and powerful.
Not sure why bytecode generated by a APLv2 project couldn't be executed in a fully open source environment.
Reference: https://github.com/erlang/otp/blob/master/erts/AUTHORS
1. Fault tolerance is almost all hardware driven. Capital market participants spent billions of dollar building reliable private networks.
2. Distributed in trading doesn't mean what FAANG are doing. Trading systems for example usually run 2 hot-warm systems with real-time replication commits, that's about it. They don't run horizontally scaled systems because network time would kill their performance.
In my experience, I haven't heard anyone asking for hot swap code and high availability (outside of trading hours).
Are there shops out there that run Erlang? Sure, but most companies don't care about Erlang simply because its value isn't better than Java/C/C++.
Unfortunately, they hadn’t tested at scale along with whatever it was servicing and as it was being rolled out it quickly ballooned in memory causing systems to swap and fall over. They eventually got it working, but the rollout was less than ideal and unfortunately an erlang project that affected a significant amount of traffic without notice was deprecated.
In my time as an engineer, I've seen quite a few Scala and Clojure apps, get rewritten in this manner.
This is all antidotal, of course.
Maybe this is a success story: someone made a useful tool in a weird language and we used it successfully for at least a year. Maybe it wouldn't have been made or would've been worse or more expensive if they'd been forced to write it in a supported language. Maybe it would've needed to be rewritten anyway.
My view is a simple one; as one of the leads responsible for it, it was a special case bit of code, something people tried to avoid touching. Nothing about it required a niche language technically, so the added difficulty of working around that was friction and risk. It wasn't that people couldn't learn the language; they could, we had lang PhDs. It's just better if you can keep people where they have existing expertise, and spend your learning points on solving problems users care about.
In contrast, for secondary products, there's a good chance most developers will never work on it at all, and of those who do a significant fraction will spend only a trivial amount of time. Adding the overhead of working in a new language to that balance is significant.
Therefore, the ideal is "Choose the best language for your main product, then write all supporting software either in that language, or a widely-used lingua franca like Python".
I’ve been moving our tools and sidecars and lesser services to do more reuse, not for the code and effort duplication reasons, but so these technologies get more burnin time before they have to do it live. We have one service that is particularly good for this because it doesn’t see a lot of traffic on average, but it bursts up to production requests levels during a certain workflow that is less time sensitive than live traffic but still gets scrutiny because it blocks a run book until it’s done. Parts of that run book can be run as often as you like if you stop before the steps that alter production state, so you can run it a few times to take the median time and see if you’ve improved or regressed.
We turn things on there and if they haven’t caught on fire we feel a lot better about flipping it on for user facing traffic.
What pain were you feeling?
Who came up with the idea/proposal to switch and how did they deliver it?
Was it hard to get people on board?
How difficult was it for people to learn Elixir?
Did people take to it quickly and/or were there people who had a hard time?
How long did the transition take to complete?
> What pain were you feeling?
The turn-around time for refactoring, adding new features, changing API endpoints, etc. was taking too long in Java.
> Who came up with the idea/proposal to switch and how did they deliver it?
The engineering team, staff engineers, and the VP of Engineering recognized the productivity issues and decided to experiment with other languages to see if a switch would result in quicker turn-around times.
First, we came up with a long list of objective metrics we could use to test various languages against each other.
Next, we made a list of languages we wanted to test (e.g., Java, Elixir, Go, Clojure, etc.).
Then, we defined a test program, including a REST API, that we would build to compare the languages.
Finally, we broke up into small teams, assigned each team a language to test, and spent about a week writing our test program in a variety of languages.
Once we were done, we had a retrospective and scored our experiences with each language we tested using the list of objective metrics we had created.
In the end, Elixir won.
> Was it hard to get people on board?
It wasn't hard to convince the team we should switch to Elixir. The team's own test data revealed that.
> How difficult was it for people to learn Elixir?
It wasn't too bad. Most of our engineers grasped it quickly. I think two factors made the switch successful:
1. Two of us already had professional Elixir experience and could mentor other team members.
2. The company purchased team licenses for the Pragmatic Studio's Elixir courses, which were invaluable.
> Did people take to it quickly and/or were there people who had a hard time?
Most of our engineers were able to pick up Elixir quickly. Some of the backend data engineers took longer though, just because they didn't have to work with it every day.
> How long did the transition take to complete?
We completed the rewrites of all our products in less than a year.
I hope this was useful. Let me know if you have any other questions.
That's pretty close to Ericsson's use case for dist; they built it to run redundant computers in the same chassis for telephone switches. It just also happens to work fairly well at much larger cluster sizes too.
What is true is that finance in almost all its guises is a world apart in terms of information technology. Closed and proprietary, ultra expensive and arcane, highly regulated etc., it is an information technology branch that evolved separately and it shows.
Whether that will remain so is an interesting question. So called "fintech" has been a thing for a while. E.g. whatsapp is famously built on erlang, so if Meta wants to turn it into a super-app (the "Asian way") you will have a de-facto application in "consumer" mobile/payments finance.
I've programmed in Python and Julia, and when I worked at an engineering (mechanical, entertainment engineering) company, Julia was great for its similarity to Matlab. I am a self-taught engineer, so I did not get pulled into Matlab in college.
Personally, I took to Erlang, so I could write plugins for Wings3D back in the early 2000s, but I never stuck with Erlang, or Wings3D (Blender3D was my choice and I even contributed to have it go opensource way back when). I like Erlang's syntax better for some reason, although Elixir's is beautiful too. I was not a Ruby programmer, and I had delved into Haskell and Prolog, so I think Erlang made more sense to me. I think Elixir has a lot more momentum behind it than Erlang, but at the root it's Erlang, so I think I'll stick with Erlang for BEAM apps. My favorite language is April[1] (APL in Lisp), and given my love of J, would be a better fit for any finance apps I might write. I am trying to convert some of the Lisp code in this book, "Professional Automated Trading: Theory and Practice" to April.
Maybe I'll write some equivalent Elixir code to compare.
http://lfe.io -- among other things, the site has tutorials and some edits of Lisp books (e.g. SICP) rewritten to use LFE.
(And, from what I've heard, LFE is being used in financial apps, though perhaps more along the lines of expert-systems than regular financial apps? (Sadly, my knowledge is at best second-hand)).
P.S. Nice to finally run into someone who has actually used Wings3D -- it gets brought up as an example of a significant Erlang project, and I know there's a community of people who were/are using it, but, since it's not a technically-oriented tool, even at Erlang conferences one is unlikely to run into Wings3D people.
It is my understanding LFE makes a lot of compromises as a list in trying to work nicely with the Erlang VM (BEAM). I really wish Gleam kept the more Haskelly/ML syntax instead of shooting for the popularity contest by becoming more Algol or C-like. Slim Whitman allegedly sold more records than the Beatles, but I would rather listen to the Beatles!
Erlang, actually; and they're still using it -- here's a paper-abstract[0] from Sept.2022 (and video of a talk[1]) about their open-source "EqWAlizer" tool[2] for statically-typing Erlang (as-is).
(EqWAlizer was discussed on an Erlang-related podcast[3], including its relationship to Dialyzer -- the original Erlang type-checking tool -- and it was briefly discussed on HN[4]).
[0] https://dl.acm.org/doi/10.1145/3546186.3552537
[1] https://www.youtube.com/watch?v=do9f2FKsKxM
Erlang (the language) is rooted in Prolog, and many of its best traits can be traced back to this fact. That everything is a pattern, and you can pattern match pretty much anything is rarely found in other languages, for example. Elixir made a mistake in my opinion when it went with a Ruby-like syntax.
Also, there are those kinds of problems where in Prolog you can express and solve them in a few lines, in other languages you struggle a lot (and at the end you just reimplement half of the backtracing engine anyway - see Greenspun's tenth rule). Why it is not more commonly used in banking / finance is one of the greatest mysteries of life.
We had along the way also looked at concurrent logic languages. So by the time we had a language and design rules how to use it most of Prolog had disappeared, though some of its syntax still remained. This language was, of course, Erlang.
While Prolog was a nice base on which to develop our ideas it was never the language we would have used in real life.
Thank you for all the time you’ve taken to explain the “why” of Erlang!
(For those unfamiliar, go check out “The Erlang Rationale” and some of rvirding’s posts elsewhere, e.g., on the thread at https://elixirforum.com/t/the-erlang-rationale-by-robert-vir...)
https://dl.acm.org/doi/abs/10.1145/1238844.1238850 -- canonical link and has a video of the related talk (streamable and downloadable).
(Sadly, without ACM membership, the paper itself is paywalled; there are copies of it online though, e.g. https://www.labouseur.com/courses/erlang/history-of-erlang-a... ).
Block parameters, implicit parentheses for certain method/function calls, uppercase significance, symbolic significance for brackets.
What do you mean by "symbolic significance for brackets?"
I spent many years in perl, so I’m of the opinion visual indicators for datatypes are actually a good thing at the point of instantiation/composition.
Not sure how to properly word it
Yea, each set of them ([], (), {}, <>) has a very distinct meaning in Elixir.
my @num = (1, 2, 3);
my $num = 25;
say $num[1];
So that last line prints 2, which is obvious by looking at it, but can be difficult in more complex code when you’re overloading names by the way the variable is accessed.
Everything in perl is a rabbit hole of details, as an aside.
Anyhow, I just appreciate that the symbols always mean the same thing. Takes a load off of my brain. Like a single character type annotation, kinda.
Comparing the two, I think Prolog may be easier for handling databases (I like Ecto, but it can be a little complex to set up and get right). Both Elixir and Prolog handle pattern-matching, but I think Elixir's syntax is nicer to work with. Of course, this is subjective. Both are great at handling list data. IO is consistently easy with Elixir whereas it can be difficult at times with Prolog.
Elixir and Erlang allow you to create supervision trees which can watch code and automatically and quickly recover from unexpected errors. Prolog's error handling and recovery can be slow. The overheard of calling a goal through catch/3, for instance, is quite significant compared to Elixir/Erlang.
I preferred the alpha syntax, which was ML-inspired, but it’s decent in its current incarnation.
I’ve always though the beam was really nice for building programming languages, and clearly that is true, as there are now more than a dozen targeting it.
Are you aware of other beam-targeting languages?
https://github.com/llaisdy/beam_languages
See you down the rabbit hole!
https://github.com/purerl/purerl & https://purerl-cookbook.readthedocs.io/ for more information. Join the PureScript discord and the #purerl channel if you want help.
With that said, I've been writing Elixir since 2015 and have worked with Erlang & Elixir since a couple of years after that (+ Haskell), so I'm both much more likely to use niche languages and I'm also well versed in using the BEAM. PureScript with `purerl` actually matches Erlang much better than Elixir does, since Elixir spends half the language and standard library trying to not be Erlang, so I find that it's a better match than Elixir even as a citizen of the BEAM, and the type safety is something I've wanted on the BEAM since I first wrote production BEAM code.
All in all I've been blown away by how solid `purerl` is. The runtime is Erlang, the language is excellent; it's what I dreamed about Haskell being but couldn't quite get.
However, as people from other domains started employing its principles, Erlang's value diminished. E. g., if we now write supervisors in Python that run servers, event handlers and FSMs written in C++, and the system works fine, we don't really need Erlang.
I'd just ignore it as low quality click bait if I were you.
But as Joe Armstrong himself pointed out in his dissertation: "indeed concurrent programs can be written in languages which are not themselves concurrent". You can write concurrent programs in Python if you want. Or even shell. As soon as you can spawn a process and send it a message - you're good.
And this explains why Erlang hasn't conquered the world. As soon as it has established the principles, as soon as it proved them feasible in practice, it has made itself redundant. The lessons we learned from Erlang were larger than Erlang itself.
Features such as the memory model and lightweight processes are intrinsic to the BEAM VM and aspects of the language (such as immutability). Erlang is a mixture of no memory management, fail-fast and embarrassingly parallel without GC pauses, and getting those characteristics in another language can’t be had without fundamental and breaking changes, to the point of becoming Erlang, which seems awfully redundant.
For example: hot upgrading. The fact that an Erlang process can tail call itself means that you can swap in a new process with the same signature at the tail call of the old process. Nobody else does this that I know of.
I can go on further. The whole set of behaviors encoded by the OTP libraries is also something that nobody else seems to do. Erlang's bit syntax is possibly the best out there even today.
I guess pattern matching finally made it to other languages. I would think that's probably about it from Erlang (pattern matching isn't exclusive to Erlang but it was one of the earlier languages with it).
None of the other programming languages seem to have learned much of anything from Erlang--and that's kind of sad.
common lisp is in a league of its own when it comes to hot reloading and debugging
The question remains :)
I would think (without knowing too much about Erlang's mechanisms) that the mechanisms of Erlang are quite different from what a Lisp runtime typically does. The Lisp runtime is just one process. Erlang is concerned with multiple processes, which are strongly isolated.
Anyhow, instead of bolting that on to your project reinventing those patterns for the millionth time you can just adhere to ̶the c̶o̶n̶j̶o̶i̶n̶e̶d̶ ̶t̶r̶i̶a̶n̶g̶l̶e̶s̶ ̶o̶f̶ ̶s̶u̶c̶c̶e̶s̶s̶ the tenants of 12 factor apps: https://12factor.net/disposability
> None of the other programming languages seem to have learned much of anything from Erlang--and that's kind of sad.
Learn you some very basic devops and you can collect on those erlang-y benefits using whatever languages/tooling/paradigms you want. A lot of it is flat out built into and managed by ye cloud providers.
Infra people squint at something like Beam/OTP and see a "control plane".
You can do that, but you won't get the new behavior on the existing connections, only for new connections. Some http servers will also curtail keep-alive requests while draining the old server processes, so you still get to pay the cost of reestablishing long lived connections, if your use case includes those.
You can do hot loading in C with dlopen and friends, but you've got to be a lot more intentional, and have the right shape of program. I did it once for a networking proxy type thing where Erlang was inconvenient (I'd need to make NIFs to get at the data and didn't want to deal with that), but I had state I didn't want to lose or serialize while making changes to the code. Of course, I then proceded to make only one or two changes. ;)
Edit: or you can do it in C the more exciting way, by updating your mmaped libraries on disk. That'd take a lot of intentional effort to not just crash, which is what tends to happen when you accidentally update instead of replace mmaped libraries. (There's a reason to use install instead of cp)
Very technologically cool, but I'd much rather inject the new functionality into the source code. From there it can it make its way through the unit tests, integration tests, deployment, health/readiness checks, and if all that passes then I'll allow it to be called.
Additionally: testing, performance profiling, and debugging are natively supported.
Recommend reading:
"Designing Elixir Systems with OTP: Write Highly Scalable, Self-Healing Software with Layers" ( James Edward Gray, II, Bruce A. Tate)
Additionally: testing, performance profiling, and debugging are natively supported.
Recommend reading:
"Amazon CloudWatch Container Insights for Amazon EKS Fargate using AWS Distro for OpenTelemetry" (https://aws.amazon.com/blogs/containers/introducing-amazon-c...)
Cheers =)
Swapping in a new process and injecting the new functionality into the source code are not mutually exclusive. You can do both!
Erlang programmers are not idiots who would swap in new processes live without writing the source code for it and testing it. They write the code, the unit tests, the integration tests, deployment, health/readiness checks, and if all that passes then the deployment tools take care of swapping in the new process with zero downtime.
Generally, you do make the changes in source code, compile it, do all your pre-flight checks, and then hotload it. Honestly, sometimes the pre-flight check is just 'does it compile', but that's philisophical; you can put whatever process in place you want. But from my experience, it's much nicer to upgrade in place than start new, move traffic, drain old (not always in exactly that order). Sometimes, it's not realistic to avoid starting new and moving traffic, but it's nice when you can.
Most people aren't patching the VM bytecode by hand (to my knowledge).
I suspect the reasons are less technical than marketing, timing, etc. It takes some experience to appreciate what it does - it's not an obvious sell like "get a webapp going in 30 min" can be for Ruby. Although Elixir/Phoenix are doing some amazing things to fix that :)
OS processes are a fine way to isolate concurrent processes if they're quite granular. It works less well when there's 10000 of them (e.g. websocket connections), and they want to share a DB connection pool, metrics, etc.
I made a blog post around this very idea, that new languages never get the adoption that they need, because existing languages simply incorporate the best ideas from the new languages.
At which point, why will anyone change the the new language if the features that are important have been fitted into their current languages.
But then you have languages that have features that you cannot replicate to other languages. You might be able to add arrow functions from CoffeeScript to JavaScript, but you won't be able to tack on homoiconicity from lisps (and macros) to JavaScript, because it simply won't match with how JavaScript is written.
I guess my own conclusion is that languages that don't really invent much can be useful in the short term (like TypeScript), they go on to die when best ideas are integrated, but languages that are really inventive (like lisp-derivatives) end up on a different branch where ideas simply cannot be borrowed to other languages, so they stay around for the long haul.
Yeah, but I specified "best features" and "important features", not "all features".
Maybe homoiconicity simply isn't that important to developers?
For example, I can guarantee you that, right now in todays development climate, there is no team anywhere that is going to allow code which has Lisp-like self-modifiying ASTs to pass code review[1].
So why would Javascript, C#, Java, etc developers bother to a) request those features, and b) implement those requests? They aren't going to use the feature anyway, no matter how powerful.
[1] Except those places who already use Lisp, because they presumably already understand it, and those teams are tiny.
The article is an obvious troll, as popularity is not an indication of utility. =)
Would finance apps be written in Rust today if all of the C++/Java applications weren't already written?
If anything Go is closer to fitting that bill, if only because of its traditional garbage collection. Applications written in Java by definition aren’t too concerned with memory management, and Rust is objectively a step backwards for them.
Rust is a more credible replacement for C++, but there I think it will be fighting inertia. Many C++ devs are actively against changing languages. I’ve also seen people “writing C++ in Rust”, using unsafe everywhere so they don’t have to figure out how to design their code to fit Rust’s model. You then end up with a kind of worst of both worlds.
The reason that such enormous software exists at banks is because the business rules are immensely complicated. All this code basically exists to deal with the complexity of the financial world, not the complexity of interacting with computers in a high performance way with correct semantics. In most cases performance is very secondary to being able to onboard programmers quickly to write oodles of code that can be modified rapidly to address changes in regulation or markets.
Java is good for this because it's a memory safe language, quite performant, super easy to learn (and quite common already) but also because you can abstract everything in a way that makes it possible to say, change the definition of currency exchange rates to account for new business rules without having to rewrite all the existing code.
Rust would require passing Box<dyn T> absolutely everywhere, at which points you are basically writing Java with extra steps. And I say this as someone who loves Rust and work primarily in Scala.
I only have a passing knowledge of Go so I can't comment on it's advantages or disadvantages much, although one of the great strengths of Go (tooling) is also very much a strength of Java (at least in large companies where there will be dev env teams that set up the Java environment for you.)
Often the law as written is ambiguous and your implementation is based on interpretation of a specific regulatory body, or even a single auditor, which frequently changes. In a country as heterogenous as the US, you don't have "business logic" per se, but just a bundle of jurisdictional exceptions, that all change out of sync with each other an incompatible ways. You often need to keep multiple implementations of the same ruleset active in your system for different products, based on when they were initiated as well. Any "changes" are actually only additions of complexity, you almost never get to remove anything.
None of these things are strictly unique to finance but they are pervasive concerns there. Codebases sprawl for other reasons too, certainly. But they necessarily sprawl for this one in finance.
Java and C++ are fine for what we do. What advantages (other than memory safety, which Java has too) do you see in Rust?
No crazy enforced OOP with a gazillion classes and inheritance, no non-sense design patterns just because the language enforces you to use OOP for everything, an amazing type system, no null pointer exceptions, great compiler error messages and so on...
Of course there are problems, like any other language, but it is crazy how it as a systems programming language is so good at expressing domain logic.
Java has a much bigger ecosystem, but judging JUST by the language design, I'd pick Rust over Java without thinking twice.
https://elixir-lang.org/getting-started/mix-otp/introduction...
Can neither substantiate nor deny but did make me wonder about all the hidden proprietary tech out in the world...
From the article, third paragraph:
Goldman Sachs built its messaging system using RabbitMQ, which runs on Erlang, in 2018. Jonathan Skrzypek (who now works for Coinbase) was running the messaging engineering team at Goldman at the time. The system had to be fault-free because the messages it was transmitting could "worth a couple million dollars," said Skrzypek. RabbitMQ was chosen because of its resilience and "reliable delivery, guaranteed delivery."
Ex-Goldman person here. To the best of my knowledge, RabbitMQ was used in spots but not where reliability was critical. Instead the main message brokers were IBM MQ and TIBCO. RabbitMQ would certainly lose messages in the event of a crash, and I'm not sure it would have been used for the main message bus given the rate of events. Additionally, Erlang was used for SecDB queries quite heavily. This was the bread-and-butter of the firm (https://github.com/saleyn/secdb)
Also orgs like GS are huge so who knows how many corners of tech they have internally
Now in the 21st century this has only got more intense. There is much more competition in this space. So finance companies that can make distributed systems right and reliable stand a good chance to the most money from the markets.
Val = SomeFunc()
Val1 = Func2(Val)
Val2 = Func3(Val1)
Yes I know you can use the functional style to minimise having to do this but you still end up seeing this pattern in real code.Kubernetes has done a good job of replacing OTP.
That said I think Erlang is still an interesting language to learn just because of how different it is.
I feel like this statement alone demonstrates a wild misunderstanding of what OTP does and is. Kubernetes is at best a replacement for VM-level scheduling, but without a slew of additional functionality and application-level interaction with the kubernetes runtime, individual servers are basically running blind in a container, totally unable to do anything that OTP provides to gen_servers for free.
Not allowing rebinding does provide a little bit of encouragement towards factoring things better, but I have seen manys a `X1` `X2` in my time :(
Jose Valim goes on as to why he made that design decision from the following: https://groups.google.com/g/elixir-lang-talk/c/w83lKZs4YS8/m...
I will post the same answer from before: I like the explicitness of pattern
matching. In Elixir, as soon as I see ^foo, I know I am matching. If there is
no ^, I know the previous value regardless if it there is one or not, will be
discarded. If pattern matching is not explicit, I always need to know if a
variable was previously defined or not to know what is going to happen. To me
this behaviour is non negotiable. In my experience, it is more likely to run
into accidental matches than into accidental rebindings.
Another possible limitation to the suggestion above can be related to macros.
Let's suppose you have a macro that stores a value in a hygienic variable:
defmacro do_something(a, b) do
quote do
var!(hello, Hygienic) = calculate_something(unquote(a), unquote(b))
end
end
Someone may call this macro multiple times but we always care about the last
value
of hello. If we make a distinction in between being assigned once and then
multiple times, the macro simply won't work. Or the macro developer would need to
work around this behaviour by inspecting the environment or we would need to
provide some sort of functionality that does it for you. Maybe this behaviour
could be built-in in var! or maybe we'd need to introduce something like:
defmacro do_something(a, b) do
quote do
set!(hello, Hygienic) = calculate_something(unquote(a), unquote(b))
end
end
We can see how this is getting complex:
1. Use = to define variables
2. Use ^ for pattern matching
3. Use := for rebinding
4. Use set! in macros when you don't care if a variable was previously defined or not
It is also interesting to point out that the := operator won't work for rebinding
inside clauses. For example, how would you make the rebinding below explicit?
x = true
case false do
x -> :ok
end
Of course, there are interesting consequences for making a distinction in between
defining and rebinding a variable by introducing something like the := operator.
We could have better control of the scope to provide better warnings or even make
it easier to implement imperative for loops:
x = 0
for i <- 1..5 do
x := x + i
end
x #=> 15
But the fact Elixir have different ways for variables to be introduced in the
scope, adding more rules can make the overall system very complex. Pipeline = fun(Functions, Initial) ->
lists:foldl(
fun(Function, Acc) ->
Function(Acc)
end,
Initial,
Functions
),
Initial = SomeFunc(),
Pipeline = [Func0, Func1, Func2, Func3],
Result = Pipeline(Pipeline, Initial).
At a certain point I grew to not mind the punctuations `; , .`I often miss language itself given how verbose things are in elixir by comparison.
The language ecosystem is pretty good with LFE for the Lispers https://lfe.io/ and https://gleam.run/ for the OCaml inclinded.
Val
|> SomeFunc()
|> Func2()
|> Func3()When strict simplicity is not the ultimately goal dare I say leaning into the monads is the way...
https://github.com/apache/couchdb/blob/23efd8e5b1aa96ef01640fec03a5fedc945ba8b9/src/couch_mrview/src/couch_mrview_http.erl#L228Having said that, nowadays anything that can't really run on AWS Lambda is a nonstarter in any company tech discussions, no matter how cool/productive it is. The operational benefits of serverless are simply too great especially when trying to scale up.
The 99.999% of tech that does not, in fact, run (or would want to run) on friggin' AWS lambdas would like to have a quiet word with you.
I've never been able to use serverless at work. I've always wanted to, but it's too risky for most companies. In my experience, they prefer to stick to tried and tested methods that have an easily predictable budget.
I may or may not know lots of people who even develop new systems that way. In part due to them not knowing better, in part due to it being an okay fit for the problem that they want to solve and in part because they haven't and won't be fired for picking what has historically been a "safe" option.
More people have probably gotten burnt in the process of developing microservices and failing at it, than have been by their monoliths rotting over time and failing to scale, unless it's in an org with a strong ops culture and the support to do microservices right (with all of the tooling, like service meshes, tracing, orchestration and so on).
I reckon that many out there have done nor microservices, nor serverless, nor have any interest to. They're just the silent majority: https://vadimkravcenko.com/shorts/the-silent-majority/
Doesn’t the BEAM runtime also have operational benefits over “lambdas”?
Also not every application or component thereof wants stateless servers? What about live collaboration, game servers or just generally holding stuff in memory for perf reasons.
[0] https://aws.amazon.com/fr/blogs/aws/new-for-aws-lambda-use-a...
[1] https://github.com/aws-samples/aws-lambda-elixir-runtime
https://github.com/alertlogic/erllambda
It is interesting in as much as the lambda functions stay hot for a period of time.