Skip to content(if available)orjump to list(if available)

Why Elixir? Common misconceptions

Why Elixir? Common misconceptions

172 comments

·July 23, 2025

Einenlum

Am I the only one who never tried Elixir just because it has no strict typing? Seems very hard for me to go back to a language with dynamic typing. Maybe I'm just wrong and I should give it a try.

lknuth

It is alleviated quite a bit bz its pattern matching capabilities combined with the "let it crash" ethos.

They have a success typing system (which isn't very good) and are working on a fuller system (which isn't very mature).

If typing is the only thing keeping you out, have a look at Gleam.

Having worked with Elixir professionally for the last six years now, it is a very mature platform, very performant and offers many things that are hard in other languages right out of the box.

crabmusket

> combined with the "let it crash" ethos

I see this phrase around a lot and I wish I could understand it better, having not worked with Erlang and only a teeny tiny bit with Elixir.

If I ship a feature that has a type error on some code path and it errors in production, I've now shipped a bug to my customer who was relying on that code path.

How is "let it crash" helpful to my customer who now needs to wait for the issue to be noticed, resolved, a fix deployed, etc.?

Muromec

>How is "let it crash" helpful to my customer who now needs to wait for the issue to be noticed, resolved, a fix deployed, etc.?

Let it crash is more about autorestarting and less about type bugs. If you have a predictable bug in your codepath that always breaks something, it just means you never tested it and restarting will not fix it. But this kind of straightforward easy to reproduce bugs are also easy to test the hell out of.

But if you have a weird bug in a finite state machine that gets itself into a corner, but can be restarted -- "let it crash" helps you out.

Consider hot reload -- a field exists in a new version of a record, but doesn't exist in a old one. You can write a migration in gen server to take care of it, but if you didn't and it errored out, it's not the end of the world, it will restart and the problem will go away.

aeturnum

Crashing is loud. You will get crashes in your logs. And you can let it happen because those crashes won't disrupt anything else - that's what the message passing gets you.

So sure, the code with the error won't work (it wouldn't work in any language - you can make an error in all of them), but you will get a nice, full stack trace and the other processes in your VM won't be impacted at all. You won't bring down the service with a crash. Sometimes this is undesirable - you could deploy a service where the only endpoint that functions is the health check - but generally people don't do that.

zdragnar

Let it crash definitely wasn't meant to be a cover for poorly typed code.

It's much more suitable as a replacement for adding try / catch everywhere and having to manually bubble exceptions.

Einenlum

Thanks for your answer! I already checked Gleam several times and it looks amazing. The ecosystem just doesn't feel mature enough for me yet. But I can't wait for it to grow.

lknuth

True. There is inter-op with both Elixir and Erlang, but thsts like early TypeScript.

If you're at all interested, I'd suggest doing the basic and OTP tutorials on the Elixir Website. Takes about two hours. Seeing what's included and how it works is probably the strongest sails pitch.

iLemming

> Maybe I'm just wrong

Yes you are. First of all there isn't such a thing as "strict typing", types are either static/dynamic and/or strong/weak. I suppose you meant Elixir has no static types. It is however a strongly typed language.

And just like it usually happens, static typing enthusiasts often miss several key insights when confronting dynamically typed languages like Clojure or Elixir (which was inspired by ideas implemented in Clojure).

It's not simply "white" and "black", just like everything else in the natural world.

You have to address:

- Runtime flexibility vs. compile-time safety trade-offs — like most things, things have a price to it, nothing is free.

- Different error handling philosophies. Sometimes, designing systems that gracefully handle and recover from runtime failures makes far more resilient software.

- Expressiveness benefits. Dynamic typing often enables more concise, polymorphic code.

- Testing culture differences. Dynamic languages often foster stronger testing practices as comprehensive test suites often provide confidence comparable to and even exceeding static type checking.

- Metaprogramming power. Macros and runtime introspection enable powerful abstractions that can be difficult in statically typed languages.

- Gradual typing possibilities. There are things you can do in Clojure spec that are far more difficult to achieve even in systems like Liquid Haskell or other advanced static type systems.

The bottom line: There are only two absolutely guaranteed ways to build bug-free, resilient, maintainable software. Two. And they are not static vs. dynamic typing. Two ways. Thing is - we humans have yet to discover either of those two.

zdragnar

You act like OP has never experienced dynamic type programming.

They clearly said they "can't go back to" it, meaning they've experienced both, are aware of the trade-offs, and have decided they prefer static types.

> Gradual typing possibilities. There are things you can do in Clojure spec that are far more difficult to achieve even in systems like Liquid Haskell or other advanced static type systems.

That's great for clojure and python and PHP, but we're not talking about them.

iLemming

You act as if I said anything about anyone's experience. "they prefer static types" can mean a whole lot of things - there's type inference, soundness, turing-completeness, type classes, GADTs, higher-kinded types, dependent types, gradual typing, structural vs nominal typing, variance annotations, type-level programming, refinement types, linear types, effect systems, row polymorphism, and countless other dimensions along which type systems vary in their expressiveness, guarantees, and ergonomics.

Dynamic typing also varies - there's type introspection, runtime type modification aka monkey patching, different type checking strategies - duck typing & protocol checking, lazy & eager, contracts, guards and pattern matching; object models for single & multiple dispatch, method resolution order, delegation & inheritance, mixins, traits, inheritance chains, metaprogramming: reflection, code generation, proxies, metacircular evaluation, homoiconicity; there are memory and performance strategies: JIT, inline caching, hidden classes/maps; there are error handling ways, interoperability - FFI type marshaling, type hinting, etc. etc.

Like I said already - things aren't that simple, there isn't "yes" or "no" answer to this. "Preferring" only static typing or choosing solely dynamic typing is like insisting on using only a hammer or only a screwdriver to build a house. Different tasks call for different tools, and skilled developers know when to reach for each one. Static typing gives you the safety net and blueprints for large-scale construction, while dynamic typing offers the flexibility to quickly prototype and adapt on the fly. The best builders keep both in their toolbox and choose based on what they're building, not ideology.

In that sense, the OP is wrong - you can't judge pretty much any programming language solely based on one specific aspect of that PL, one has to try the "holistic" experience and decide if that PL is good for them, for their team and for the project(s) they're building.

dmz73

Runtime flexibility is not restricted to dynamically typed languages, it just happens to be less available in some of the popular statically typed languages. Error handling, expressiveness, testing culture, meta-programming and gradual typing have nothing to do with static vs dynamic typing. The main "advantage" of dynamically typed languages is that you can start writing code now and not thing about it too much. Then you discover all the problems at runtime...forever. Statically typed languages force you to think about what you are doing in advance a lot more which can help you avoid some structural issues. Then when you do refactor computer helps you find all the places where you need to change things. Dynamically typed languages force you to write more tests that are not required in statically typed languages and that might prompt you to write other tests but if also increases the chance you just give up when you start refactoring. Finally, after some time has passed and few updates have been applied to the language and libraries, you may not have a working project anymore. With statically typed languages you can usually find and fix all the compile errors and have the fully working project again. With dynamically typed languages, you will never know until you explore every line of code, which will usually happen at runtime and on the client computer.

iLemming

Sure you're right on most of this, but allow me a slight pushback here. I am sorry, I am inclined to use Clojure/Lisp in my examples, but only because of its recency in my toolbelt, I could probably come up with similar Elexir examples, but I lack intimate familiarity with it.

- Dynamic languages can harbor bugs that only surface in production, sometimes in rarely-executed code paths, yes. However, some dynamically typed languages do offer various tools to mitigate that. For example, take Clojurescript - dynamically/strongly typed language and let's compare it with Typescript. Type safety of compiled Typescript completely evaporates at runtime - type annotations are gone, leaving you open to potential type mismatches at API boundaries. There's no protection against other JS code that doesn't respect your types. In comparison, Clojurescript retains its strong typing guarantees at runtime. This is why many TS projects end up adding runtime validation libraries (like Zod or io-ts) to get back some of that runtime safety - essentially manually adding what CLJS provides more naturally. If you add Malli or Spec to that, then you can express constraints that would make Typescript's type system look primitive - simple things like "The end-date must be after start-date" would make you write some boilerplate - in CLjS it's a simple two-liner.

- Static type systems absolutely shine for refactoring assistance, that's true. However, structural editing in Lisp is a powerful refactoring tool that offers different advantages than static typing. I'm sorry once again for changing the goalposts - I just can't speak specifically for Elixir on this point. Structural editing guarantees syntactic correctness, gives you semantic-preserving transformations, allows fearless large-scale restructuring. You can even easily write refactoring functions that manipulate your codebase programmatically.

- Yes, static typing does encourage (or require) more deliberate API design and data modeling early on, which can prevent architectural mistakes. On the other hand many dynamically typed systems allow you to prototype and build much more rapidly.

- Long-term maintenance, sure, I'll give a point to statically typed systems here, but honestly, some dynamically typed languages are really, really good in that aspect. Not every single dynamic language is doomed to "write once, debug forever" characterization. Emacs is a great example - some code in it is from 1980s and it still runs perfectly today - there's almost legendary backward compatibility.

Pragmatically speaking, from my long-term experience of writing code in various programming languages, the outcome often depends not on technical things but cultural factors. A team working with an incredibly flexible and sophisticated static type system can sometimes create horrifically complex, unmaintainable codebases and the opposite is equally true. There's just not enough irrefutable proof either way for granting any tactical or strategic advantage in a general sense. And I'm afraid there will never be any and we'll all be doomed to succumb to endless debates on this topic.

sammnaser

> The bottom line: There are only two absolutely guaranteed ways to build bug-free, resilient, maintainable software. Two. And they are not static vs. dynamic typing. Two ways. Thing is - we humans have yet to discover either of those two.

That's true but some languages don't let you ship code to prod that multiplies files by 9, or that subtracts squids from apricots

iLemming

> that multiplies files by 9, or that subtracts squids from apricots

I don't understand why when someone mentions the word "dynamic", programmers automatically think javascript, php, bash or awk. Some dynamically typed PLs have advanced type systems. Please stop fetishizing over one-time 'uncaught NPE in production' PTSD and acting as if refusing to use a statically typed PL means we're all gonna die.

ThinkBeat

There is no hard YES or NO, when it comes to typing. It is not a religion. (but it sures feels like it sometimes)

There are really good arguments both ways.

Just use what you need or go with whatever your current project dictates. Over time you will probably feel drawn to both, for different reasons.

iLemming

> Over time you will probably feel drawn to both, for different reasons

I agree 100%. At first I liked C# and Java types, but then I moved to Python and I was happy. Learning some Typescript pulled me back into the static typing camp, yet then I discovered Clojure it revealed to me how needlessly cumbersome and almost impractical TS type system felt to me in comparison. Experimenting with Haskell and looking into Rust gave me a different perspective once again. If there's a lesson I've learned, it's that my preferences at any point in life are just that - preferences that seldom represent universal truths, particularly when no definitive, unambiguous answer even exists.

davidclark

Well written typespecs + dialyzer catches most things you’d want to catch with a type system: https://hexdocs.pm/elixir/typespecs.html

There is also pattern matching and guard clauses so you can write something like:

def add(a, b) when is_integer(a) and is_integer(b), do: a + b

def add(_, _), do: :error

It’s up to personal preference and the exact context if you want a fall through case like this. Could also have it raise an error if that is preferred. Not including the fallback case will cause an error if the conditions aren’t met for values passed to the function.

ludicity

It's not so bad in Elixir for various reasons. Firstly, they're doing some work on set-theoretic types.

https://hexdocs.pm/elixir/main/gradual-set-theoretic-types.h...

There's also tooling like dialyzer, and a good LSP catches a lot too. The language itself has some characteristics that catch errors too, like pattern matching and guard clauses.

With all that said, I'm still very keen for static typing. In the data world we mostly start with Python without mypy, and it's pretty hard to go back.

rendaw

I tried it for a job interview, and it was awful - because of no static typing. I spent most of my time tracking down dumb type errors, compounded by various language footguns (I can't remember exactly, but I think for example making a typo on a field name in a for loop condition is treated as "condition false" and so the for loop just doesn't do anything, no error).

It seems like the Elixir/Erlang community is aware of this, as is Ruby, but it's a rather large hole they have to dig themselves out of and I didn't feel particularly safe using the tools today.

I've heard a lot of good things about the Erlang runtime and I did really like Elixir's pipe operator, so it was unfortunate.

kingofheroes

Pattern matching makes up for the lack of static typing to me. It provides nearly all the same benefits especially when used with guard clauses.

victorbjorklund

Maybe try Gleam? 80% of the goodies of Elixir is the BEAM anyway and you get that in Gleam too.

harrisi

I believe you meant static typing. There's active ongoing work in this space, and Elixir is actually gradually typed now. You can read more about it in the docs: https://hexdocs.pm/elixir/gradual-set-theoretic-types.html

williamdclt

I used it being a big proponent of the TS type system and I definitely missed it greatly.

They are actively shipping a type system for Elixir though, which as far as I understand is pretty similar to TS so, great!

codyb

Type systems in this space seem to take a long time and never quite reach completeness. At least that's the experience I've taken away from occasionally glancing at Erlang's Dialyzer project every now and again which I don't think has ever reached any semblance of the maturity of something like TypeScript.

But pattern matching in Erlang does do a lot of the heavy lifting in terms of keeping the variable space limited per unit of code which tends to reduce nesting and amount of code to ingest to understand the behavior you care about at any moment.

nichochar

Elixir and Phoenix are very underrated.

It combines the "opinionated" aspects of ruby and rails and the power of erlang. The BEAM is like no other runtime and is incredibly fun to work with and powerful once you get how to use genservers and supervision trees.

We use Elixir for Mocha, and my one issue with it (I disagree with OP on this) is that live-view is not better than React for writing consumer grade frontends. I wish Phoenix took a much stronger integration with React approach, that would finalize it as the top choice for a web stack.

mike1o1

My current project is using React Native (for native and web) and getting GraphQL setup was initially a pain, but having React and GraphQL subscriptions gives me enough of the "live" functionality, but without having to worry about connection issues. With gql-tada, I get fully typed experience on the front-end too.

If I didn't need native functionality, I'd probably just use the recently released `phoenix_vite`: https://github.com/LostKobrakai/phoenix_vite

POiNTx

Something like https://github.com/mrdotb/live_react might be what you're looking for.

jamauro

Yeah it’d be nice if they had a mix task to include your js frontend of choice and it “just worked”. Many have used inertia with success. I’m taking a different approach and pairing svelte with Phoenix channels.

4b11b4

Any thoughts on Inertia for including React into the picture?

andy_ppp

Yes, it’s always a surprise to me that, given how great Elixir is, it didn’t take over backend development. It seems so much better suited to doing something similar to microservices without a lot of the overhead you’d think people would love it. It always seems that fads win and projects with extremely tight concepts remain niche.

tl

While Elixir is my current favorite language to hack in, it is very alien and downright hostile to integrating with existing systems. For example, relational database support was postgres focused for a long time (to the exclusion even of SQLite and continued inability to talk to Oracle). Then you have articles like https://dashbit.co/blog/you-may-not-need-redis-with-elixir pushing ETS over Redis. While it's a valid argument, it's not adoption-friendly.

Clojure brings about half the novelty of Elixir, runs on the JVM and still struggles to replace Java.

stanmancan

What’s wrong with that article?

For what it’s worth, I’ve been using Elixir professionally for a few years now and haven’t touched Redis once.

Not sure why telling people they don’t need another service is bad for adoption?

jjtheblunt

i understand, but i am not familiar with how one allocates hosts to create a cluster of beam instances across which elixir/gleam apps are running.

is there a popular pattern, perhaps as used by whatsapp, i guess?

OkayPhysicist

One thing the author didn't mention is how incredibly polished the primary ecosystem of documentation, standard library, and tooling is. The Elixir standard library is incredibly consistent in order to support Elixir's piping operator, such that the first argument will basically always be the information you want passed from the function before it. In comparison, I frequently have to check the docs to confirm argument order on any lesser-used function in Python, Javascript, or C#. Then there's the fact that the second-layer of standard library, the OTP inherited from Erlang, which is expansive to the point of containing most things you'd want to do on a server. The documentation, in turn, is the gold standard that I (typically negatively) compare all other language docs to. It's organized, discoverable, and covers not just the "what" but the "How" and "Why" exceptionally well, not just at the function level, but the module layer as well. Frankly, only MDN comes close. All combined, it's just an incredibly productive language.

danman114

Hi! I recently tried to get into Elixir as an antidote to an acute javascript-fatigue...

To my surprise this there isn't really a good mobile story to build mobile apps for both Android and iOS with it, although it looks like it could be a great option for quick turnaround mobile apps with a web- or native frontend...

I know that there is something being worked on, eg. LiveView native: https://native.live/ , but that seems to target two entirely different frontend frameworks, one for each platform...

I started using capacitor as a wrapper for a HTML frontend, but I think I might potentially run into trouble when I'd try to move into production builds...

I think there's some space for research and maybe some nice starter packs / tutorials there... Because I think it is a big and pretty relevant market for browser-based apps, which Elixir seems to be very well suited to!

I'm grateful for any additional pointers, peace out! :)

jabwd

This language and its upsides (that come from the VM) really are not for application development in this manner. I'm sure you can make it work somehow but its like using a tank to get groceries. Reliability, scalability, aren't concepts relevant to apps on mobile phones. If an app crashes to the homescreen thats fine, if your entire service goes down that's another. Would be fun if someone could prove me super wrong here but if you want to learn Erlang/Elixir/Gleam or anything BEAM I'd pick a backend project.

hinkley

The continued lack of DOM access from wasm is keeping a lot of potential programming languages out of this space.

andrewflnr

Uh, yeah, it's primarily a backend language, with any frontend stuff being either a thin layer or experimental, AFAICT. OTOH, doing a more traditional backend-heavy web app might be just the thing for JS fatigue. :)

hangonhn

I've been wanting to learn Elixir for a long time but is it worth learning it without knowing Erlang first? I'm not against learning Erlang but just curious if Erlang is a good thing to know before tackling Elixir.

spike021

I only learned Elixir because the company I currently work for is an Elixir shop. I've basically ignored Erlang since I started here, other than the occasional library being Erlang.

I don't think it's really impeded my ability to learn or use Elixir. But I could also see how learning it and the underpinnings for Elixir could aid understanding too.

Towaway69

Erlang is definitely worth learning but definitely not required by Elixir.

Learning the concepts that embody Erlang such as tail recursion and function matching, make Erlang worth learning. Erlang is also a special mix of Prolog and Lisp.

pivo

To add to this, Erlang is a very simple language that you can learn in just a few days. I don't know Elixir but I assume that, as is the case with Erlang, the more difficult thing to learn is OTP and not the language itself.

For me Erlang was worth learning because it's so interestingly different to many other languages because of its Prolog roots.

thibaut_barrere

Yes, it is worth it to learn Elixir without learning Erlang, absolutely.

_acco

I consider myself expert-level at Elixir and did not learn Erlang first. Couldn't write a single line of Erlang today unaided if I tried.

I picked up Joe's Erlang book years after out of pure joy/curiosity.

Especially with LLMs, totally unnecessary.

heeton

~5 year pro elixir here, various systems in production, I don't know any erlang.

cybrox

We've been running Elixir in production for 5+ years and most of our team only know some very basic erlang data structures for working with the :dbg module on live systems.

Erlang knowledge is not needed for building products with Elixir at all unless you want to go very in-depth.

arrowsmith

It is absolutely 100% _not_ necessary to learn any Erlang at all before learning Elixir. I've been developing with Elixir for 5 years and still have never written a line of Erlang.

You don't need to learn OTP at first either — it'll just slow you down and confuse you. Learn Elixir syntax and semantics, learn how to build a Phoenix app or whatever, then dive into OTP once you're comfortable with the basics.

runjake

You don't need to learn Erlang first.

parthdesai

You can get very very far in Elixir without even knowing about an acronym called OTP.

ngruhn

The only thing putting me off is the lack of static typing. But I'm open to be convinced that this doesn't matter.

_acco

It doesn't matter as much as you think. I believe this is in part due to how assertive most Elixir code tends to be. [1] These assertions not only aid the LSP and can cause compiler warnings/errors, they also help LLMs just like types do.

Still, every release now contains new type system features. Next up is full type inference. [2] After that will be typed structs.

[1] José Valim giving his balanced view on type systems: https://www.youtube.com/watch?v=giYbq4HmfGA

[2] https://hexdocs.pm/elixir/main/changelog.html

kingofheroes

Pattern matching makes up for the lack of static typing for me. Combined with guard clauses it feels even stronger than static typing.

foxygen

They are working on a type system.

cpursley

Fwiw, Claude 4 is really good with Elixir, including whipping up quality test suites.

spike021

Can agree with this. I have had some funny hallucinations, though, where it mixes up Elixir keywords with totally unrelated to programming things and then acts very confident that said things are in Elixir. So you just need to be a bit skeptical and double-check it. But that goes with the LLM territory anyway.

Jonovono

Ya, it one shotted a Server driven ui app using elixir backend, expo with phoenix channels. Was impressed.

ch4s3

> whipping up quality test suites.

YMMV, but I think it writes fine unit tests, but really sub par functional or end to end tests that need to check business logic. I think that's just a hard case for LLMS and not an elixir issue though.

mike1o1

I've been using Elixir for about a year on a side project and I've been enjoying it more than any other backend I've used (Node, Rails and C#). I recently discovered Ash and I feel like after that initial learning curve my productivity (and code quality) has improved quite a bit.

I wish Elixir had more mindshare beside just LiveView and "real time" type functionality. Even building a GraphQL/JSON endpoint without real-time requirements, the functional nature (no side effects), pattern matching and ruby inspired syntax makes writing plain old JSON controllers a joy.

While Elixir might not have a package for every use case under the sun, the low level primitives are there.

realusername

Personally while I enjoy Elixir/Phoenix, I didn't like Ash because there's way too many keyword DSL to learn.

It's like Rails except that there's much more resources for Rails to find if you made a mistake in the DSL

mike1o1

Yes, the learning curve is a extremely high. It took a few false starts over time, but after the "Ash book" came out, I gave it a more serious try and it finally started to click for me.

I think it helped that at the time I was trying to build some pretty advanced filtering functionality using Ecto and was having a pretty tough time. While searching for solutions I saw a few mentions of Ash and that it could solve the problem out of the box.

After a few days of experiments, I found that it was able to do the filtering I wanted out of the box and was even more functional than what I was trying to build.

For reference, I was trying to add some tagging functionality to a resource and I wanted to be able to filter by that tag, including multiple tags. Can I do that in Ecto? Of course, but Ash provided that out of the box after modeling the resource.

pmarreck

So if you're comfortable with Ecto and SQL, you can safely skip over Ash?

pmarreck

Except that it's not like Rails in the sense that in Rails, you will eventually develop extremely difficult to debug race conditions thanks to mutability that Elixir lacks.

Source: Has worked on million-line Ruby on Rails codebase

KevinMS

Some don't use it because the performance on anything other than IO is just bad. This isn't just because its "not compiled", but because it has a scheduler taking up cycles and it enforces immutability, when can be brutal for some tasks when mutability can really speed things up.

kingofheroes

I just started learning Elixir recently and I'm honestly loving it. Pattern matching is awesome and how it approaches concurrency and async work was so easy to wrap my head around. Pragmatic Studios has a great tutorial.

throwawaymaths

if the author is reading this a minor edit should be that whatsapp uses erlang, not elixir.

matthewsinclair

Yeah, that’s a fair point.