Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: Anyone Using Elm in Production?
88 points by sebst 48 days ago | hide | past | web | favorite | 72 comments
What is your experience so far?

How do you cope with basically not having deeply nested components?

We've been using Elm since Nov 2016 right after the 0.18 release to rewrite an old B2B web app.

- The system has 150+ users that was migrated over night and has been online for about 2 years now.

- No runtime exceptions in production. In testing the only thing we had was "Stack size exceeded" in Internet Explorer due to a poorly written time zone module.

- Translation was solved with one build for each language to avoid passing down the model everywhere.

- Coding takes more time but things don't gradually turn into spaghetti and refactoring is a breeze.

After the initial functional struggles it feels like writing "the code of your life". Overall, a very positive and fun experience and I don't regret us betting on this new fairly untested technology. And none in the team had lots of prior SPA experience so we had to learn new stuff anyway. Almost as good a tech choice as when we decided to use gevent or MongoDB but for a very different problem.

This was for a custom client project and not our main 46elks service which is an API that mostly uses Python.

I used Elm to build an AI/IQ quiz in support of an event Fidelity and The Atlantic put on last year (https://web.archive.org/web/20180928051336/https://www.intel...).

I found Elm to be very productive. Custom types allow you to codify your business logic and _can_ make bogus application state impossible; the compiler's error messages are helpful and the steps to resolve the problem are (usually) obvious; the FLOSS libraries are excellent (elm-css, elm-test); the community is very supportive; JavaScript interop is safe and simple (mostly -- decoding can be a little confusing at first and could use more documentation and tutorials); the compiled JS is _small_ and the applications feel very snappy.

I didn't have any issues with nesting. Your views unfold to match your model. I found creating sub-models for each "page" within my app to be very intuitive -- these choices became obvious as I started prototyping -- and it's easy to share partials across different page views.

We've been using Elm in production for about 4 years (currently about 300,000 lines of code) and the experience has been wonderful! We rave about it.

Also, we're hiring! No Elm experience required; over the years we've had many new hires pick it up on the job. :)


Also, the creator of Elm works at noredink, so if you really want to learn it, there's probably not a better place. ;)

LOC should have something like crop factor in camera sensor world. It would be useful measurement for LOC that's vertical style.

Yes. The deeply nested components thing isn’t an issue at all. You build “components” as stateless views. It’s fundamentally the same as building an application out of all stateless components in redux.

Your model (the central state) becomes larger and more complex, but the size of your update function doesn’t expand as much as you’d think.

Meanwhile, the benefits from type-safety, pure functions, and extremely well-designed libraries like elm/parser & elm-UI are really terrific.

What is meant by "deeply nested components" and why can't you do them in Elm?

This has to do with state partitioning.

The official Elm Architecture tutorial used to contain some examples of encapsulating functionality into modules that would then be reused. The pattern presented there was abused by some folks and some problems that were introduced by state partitioning started to appear. There was a lot of talk about boilerplate and inter-component communication. A lot of these problems could have been avoided by not being so aggressive with the partitioning and so, "thinking in terms of components" has been discouraged ever since.

You can still define components by implementing the model/update/view triplet pattern but the main recommendation is to do it only when this is unavoidable (e.g. Pages or highly complex widgets).

I think “deeply nesting components” means dropping a stateful component (view+behaviour+state) anywhere in your app without anything else changing. That’s not possible in Elm since the only place to store state is the central state storage. Which makes perfect sense, but often freaks people out, since it’s an uncommon design constraint.

With only one store, how do you keep your state reasonably organized when you get up to hundreds of pieces of data to manage?

And what do you do about generic reusuable components that need state? Say a typeahead search that needs to track the input string and the list of results from the server?

Your state can be a tree, if it needs to be, so you can nest.

A normal practice is to have a model per page. For e.g. https://github.com/rtfeldman/elm-spa-example/blob/master/src...

And you can have another item next to it for global state if you need to. https://github.com/ohanhi/elm-shared-state explains one way to do this

If you really really really can’t live without a statefull component, you can always build a custom element (which can be a wrapper around an elm app). But reusable views with fairly complex state are used; they require a little bit of wiring up, but it means you know exactly where to look when there’s a big/problem.

You can think of each root-level branch of the state tree as its own "model". In redux (I haven't used elm much) I implement generic components by finding a property that can be used to derive a unique key and creating an entry for each component in the reducer.

I don't use it myself, but I was recently at Oslo Elm Day, where a consultant at The Norwegian State Railways shared his experiences with it (which were mostly good): https://youtu.be/yE9PKFI19RM

We've been using Elm in production for the last year to power an app used by 100,000 public school students in the US, and it's been fantastic.

The Elm language and framework really do live up to their promise: it's a delightful development experience. Despite rewriting our entire 4-year-old UI we've had remarkably few bugs despite multiple large refactors. The whole team was new to Elm when we started, and now everyone's an advocate.

Re: components, I'd echo what others have said. Because the view code can't have side effects, components become much simpler and a whole category of the problems we've had in one of our Javascript apps just don't happen. You sometimes will want to separate out logic for subsystems in your update function, but that's pretty well supported.

Also, if you're interested in working in Elm and making a measurable difference in student learning, we're hiring!


Also also, if you're interested in meeting the Elm community in person, we've just announced the speaker lineup for Elm in the Spring, a new 1-day conference in Chicago in April -- we're really excited :D :D :D


Elm made me hate working with Javascript in my job, and the differente is brutal. I don't believe in silver bullet but this is the domain where Elm shines: frontend development. I love every aspect of it. Elm is a very simple language, generates very small assets with a really fast compiler, gives us guarantees of no runtime exceptions in production, easy refactoring (in JS it would be a nightmare), has a time travel debugger (that shows your application state in any given moment), nice compiler error messages, and an incredible architecture which inspired redux (TEA) but is much better and simpler. There are problems ofcourse, for example not every Web API is covered yet, but it's possible to use Js ports to communicate with Elm.

Just out of curiosity, how often do you use time travel debugging? I have redux dev tools and can use it on any of my apps, but I've never felt that it was more useful than the step debugger. The first time I set it up I thought "huh, cool" and then never used it again. There's also the issue of side effects like ajax requests that interact with the outside world.

I had the same problem with time-traveling in react/redux. Everything has to be in the store for it to work, and since it's hard to make reusable components using the store, some things often end up outside. Then time-traveling becomes buggy. But since it's impossible with side-effects in elm, you can always trust it there. I use it pretty often to jump between states. The UI is not as good as redux-devtools and as feature-rich, though, that part I miss.

What about ajax requests though? What if you are debugging a component that sends a DELETE request?

It doesn't end up spamming requests the same way as in react, as there is no "componentDidMount" that can trigger side-effects. In elm it's just different states being rendered.

Ah sorry, I didn't mean side effects in lifecycle methods, I meant DOM events like click, etc. If you click a button that deletes a resource on your API, there is no time traveling because the outside world doesn't time travel along with your debugger (unfortunately). :)

You can isolate your side effects somewhere, but they still have to respond to actions/events/messages so if your time traveler dispatches actions you'll end up making duplicate requests.

I could be wrong, but I don't think Elm re-triggers side-effects when you go back in time. It just brings back the state as of that moment in time.

Everytime. If anything goes wrong I just see the message (action in redux) and see the current state in that time, so I can understand what happened. In some cases it is more effecting than sending a log.

Ah, I see. I use a customized redux logger that shows the before/after state and the action payload. That is what I've always used for trying to diagnose bugs so I've never found a reason to use the time travel tools.

Using Elm for an admin interface (not web-facing).

Elm is incredibly reliable (that's why we experimented with it in the first place) as well as very productive once you get used to the Functional paradigm.

Refactoring especially is a breathe (as long as it compiles, it usually works) and we didn't need to test the frontend for it to stay sane.

We even started covering more and more of our admin's old views with it and are on our way towards an SPA.

I'm using elm 0.19 for an internal company wide tool, backed up by elixir with a graphQL api.

You have to see the implementation of libraries like https://package.elm-lang.org/packages/dillonkearns/elm-graph... to really appreciate what elm is trying to do. Maybe even read this https://package.elm-lang.org/help/design-guidelines

So every package is documented and quiet easily understandable. So whenever I need to go back into angular land - most times dependencies don't even have any docs maybe a readme if your lucky...

We do https://www.mybrocante.fr, it's Elm almost exclusively save for legacy parts we dare not touch with a 10-foot pole, and it's the best dev experience I've ever had =)

Yes, replaced few rich and reasonably complex UI components in admin interface that were previously developed in Adobe Flash (developed in the times when html wasn't as expressive for more visual/interactive UIs). The end users did not notice any difference.

The language is pure joy to work with. No issues with "deeply nested components", just use a function to render a "component", add data needed for the rendering as a function parameter, handle the events emitted from the "component" in the update-function.

I’ve used it on a deployed and used project app. On a substantial commercial internal project. And have 2 other apps in the works.

I’ve used ports and custom elements to integrate JS code.

I’m convinced Elm is an excellent way (and my preferred way) to build frontend apps.

The learning curve is a bit tricky. I think the path to toy apps is straightforward and fun. The path to “real world” apps requires a bit more effort. Expect to do some homework, hang out in forums etc.

I've been picking it up lately and I'm curious if you have any links to non-trivial application sources. I'm curious how the architecture scales and how it handles cross cutting concerns.

You'll probably want to watch Richard Feldman's [Scaling Elm Apps](https://www.youtube.com/watch?v=DoA4Txr4GUs). I built [Component Result](https://package.elm-lang.org/packages/z5h/component-result/l...) to help with a pattern that occurs when scaling up apps. I'm not clear what you mean by or expect to be problematic with by cross-cutting concerns. Feel free to ping me, z5h, on the Elm slack.

Yes, we're using in production in http://getsurance.de and it has been great.

About nested module, they are not necessary at all. Check "The life of a file" by Evan Czaplicki - create a new file if Model/Update gets too big, there is no need for upfront component partitioning.

I built https://listenparadise.org using Elm, and the code is open source: https://github.com/azer/radio-paradise/tree/master/ui

Although it's recommended to not build components with states, you could still do it if you think it's necessary for your app. I documented the codebase structure I used at; https://azer.bike/journal/elm#codebase-structure

It's used in two applications at CityBase. Given that I didn't write any of it, I can't answer the deeply nested component question. Our experience: It works well. However, we will probably stick with React or something else going forward.

>>Our experience: It works well.

What are the reasons you wouldn't consider using it going forward?

Here at https://legalstart.fr, we have been using Elm for a few months now, and this experience has been quite positive.

What we liked:

- the compiler: not only does it prevent a lot of bugs, it allows us to refactor large portions of the code base fearlessly. Also, the compiler messages are often very easy to understand.

- the documentation: the guide is excellent.

- The Elm architecture: the fact that this is the only framework that you can use makes things easier, notably for junior developers who are not lost into a sea of choices.

- The Slack community is very responsive, notably via its Slack record channel: https://elmlang.slack.com/. I also found it to be quite friendly.

What we struggled with:

- In our experience, the hardest part has been to deal with JSON Encoders / Decoders. But it got smoother when we got used to it.

- The fact that the 0.19 version was new had some negative effects, eg obsolete docs or unavailable tools. It has gotten much better by know.

If you're new to functional programming Elm will require some getting used too, but we quickly got 4 developers of various experience / backgrounds up to speed. I believe having one developer who already knew Elm and advocated / taught it the beginning helped speedup this process a lot.

About nested components: as stated before, they are much less necessary than one might think; but otherwise this post might be helpful: https://medium.com/@alex.lew/the-translator-pattern-a-model-...

Last but not least: if you are interested in working in Elm (or React), we are looking for creative frontend developers !: https://jobs.smartrecruiters.com/Legalstart/743999665887249-...

I was part of the team that built an editorial admin panel for the most read news site in my country. The initial development phase ended around three years ago and it's been in a sort of continuous development mode since then. A whole bunch of people have added features to the codebase (and upgraded it from 0.16 to 0.17 and 0.18) after me and the other original devs left.

It is still going strong and is so reliable that there's no need for dedicated developer for that project. I honestly can't imagine any sort of JavaScript project could have survived through the years that well.

At CurrySoftware we use Elm for all of our frontend needs.

Most recent example: https://www.pavoq.com a SPA built with Elm and Rust

FYI I think you have a problem, at least in latest Firefox for Mac https://imgur.com/Sd9960X. Those messages are being logged multiple times a second.

Will look into it! Thanks!

ahahah, client side shaders as a service!! I love it, very smart!

Discussed in HN a couple months back: https://news.ycombinator.com/item?id=18870796 .

IBM App with Elm for most of the front-end: https://discourse.elm-lang.org/t/ibm-releases-elm-powered-ap...

[Disclosure: I'm an IBMer - but not involved on this project]

While I'm glad to see that there are many positives for using Elm, I'm curious about the "lessons learned" that come about from maintenance of the project.

That's kind of the problem, unless you have more features to work on, there is little to maintain in the old sense. https://www.youtube.com/watch?v=RFrKffrKCeU

Yes, we're using Elm in production for two years now. Rewriting legacy Ember application into Elm, and it has saved our sanity. To be honest, we dread the JIRA tickets that concern Ember and not Elm :D

Re deeply nested components: we have components about 2-3 levels deep, and while it's a bit more code and boilerplate than having a flat model, it's been just fine. Don't worry about it.

If your question is whether Elm is mature enough for production, the answer is yes. There are some companies out there, but don't let their opinion condition your experience.

Rather than relying on other people's opinion a better experience for you would be to port one sub-component of your existing system to elm and see how it goes from there, while you gain trust and experience in the new system.

Yep, used in production here - https://www.robustperception.io

Would also be interesting to hear the reasoning of someone who has seriously considered using Elm but ended up with not using it.

It's a neat little language. The benefits are real when coming from JS, but not that special when you consider other languages. Basically everything said in favour of Elm is completely true, but it's not the whole story.

The ecosystem offers some trivial packages, but the hard stuff is missing. JS interop is intentionally quite painful. I'd consider it sufficient for fairly trivial SPA use, but lacking for anything large or anything requiring browser APIs.

The language development is a big red flag: virtually all commits have been made by a single developer. There are no RFCs, and the future direction of the language is very unclear. Any discussions about potential improvements are immediately killed. Releases are infrequent, and may cause very significant breakage, depending on your application.

It's probably the best thing in the JS ecosystem in a long time and i really want it to succeed and to use it more, but the current state isn't that great. Maybe in a year or ten.

The bus factor of Elm is pretty bad compared to more "open" projects with RFCs, a dozen or so contributors, etc. In some ways it still feels like someone's private project.

The problem with having a bus factor of 1 is that no one sees it as a problem until it becomes one.

While it seems like a bus factor of one, my understanding is that there is a plan in place (probably from the people at noredink). Even if not, the code is open source and can be forked, which should only be the very very last option.

I recently did a talk at Oslo Elm Day where I talked about our experience with Elm at my company after using it as the main web langauge for the past 18 months: https://youtu.be/yE9PKFI19RM

TL;DR: - The experience has been terrific. - Best compilator I have ever worked with. - Mostly great tooling. Love the auto-formatter. - Great libraries - No major issues, some small itches but nothing that can't be worked around. - No runtime errors in 18 months. - Very maintainable code - New team members quickly becomes productive in Elm, even with no prior experience (It helps to have someone with experience on the team to guide the learning and answer questions).

When it comes to nesting we sometimes make use of a component-like pattern, where we have modules with their own state, messages, update and view functions that are used by the main functions. To see an actual example of this check out this SPA example: https://github.com/rtfeldman/elm-spa-example/blob/master/src...

What exactly does elm offer?

Adding to others, with disclaimer that I haven't built a large application yet so these are relative newbie comments:

1. An amazingly helpful compiler. The best I've come across for identifying problems, describing them in a meaningful way, and suggesting how to fix.

2. A wonderful synergy between language and architecture. Various others have copied Elm's model-view-update architecture (React, F# SAFE) but as they're libraries, they don't feel quite as well-integrated.

3. An excellent, helpful community.

4. A BDFL in Evan who is focused on considered design and careful evolution over "move fast and break things". Some will (rightly) challenge if this is good: Elm 19 broke a lot in 18. For me personally, I much prefer Elm's thoughtful, well-considered evolution over the volatility in the wider javascript ecosystem

5. Some nice libraries. Elm-ui, for example, provides a different way to do lay out (no CSS). Again that's not for everyone - but useful if you're not a CSS guru.

6. Strong static typing with powerful type inference.

There are definitely downsides. The full-on, no-compromises immutability means there's some overhead in dealing with e.g. http request/responses or js interop. But there's corresponding value in the resulting guarantees in the code.

As a newbie I'm really taken with Elm; it's a refreshingly stable and integrated enclave in the otherwise volatile front end space. YMMV of course

What about good IDE?

The Elm plugin for IntelliJ is really good.

Thanks, that's awesome. Really gonna try it next time then.

A strictly typed pure functional language that generates JavaScript. That, along with a clever compiler, makes them claim that apps built with Elm don't have runtime exceptions.

I'm curious what Elm offers that cannot be done in TypeScript.

Much stronger type guarantees. TypeScript's strength and weakness is how it fits JavaScript like a glove. Elm is a different language entirely, so it can provide much better soundness. It's also a simpler language than JS / TS. TypeScript, being a superset of JS, has a lot of baggage. Elm is pretty small and conceptually simple. Elm is also a framework, not just a language, so it guides your team into building things in one, consistent way (for better or for worse). Finally, the Elm compiler is very good. It produces small, fast build artifacts. Compare the bundle sizes of Elm with the other competing frameworks here[0].

[0] https://github.com/gothinkster/realworld

You can do way less in Elm than you can do in TypeScript. Counterintuitively this makes your code much more robust.

Elm is far more opinionated. There is only one framework you can use. The type system is much stronger with no escape hatches. It is impossible to mutate variables. Interfacing to javascript is much harder, and there is only one way to do it, and any results coming back from javascript have to be checked and handled to ensure it is as you expect.

As mentioned, the type system is much, MUCH stronger (you basically can't get runtime errors at all unless you put debugging statements in).

The redux-like (well, more like redux is elm-like) is baked into the type system so you know it will be done "right".

And thanks to the above, there's less bikeshedding within the team from people who want to reduce boilerplate for bad reasons and make the app worse.

Could you do the following in TypeScript?

Can you, for any button in your interface, at any point in time, reliably calculate at runtime what your page's data model would look like, and if there were going to be any side effects, if you were to click on that button - but without clicking on it or invoking its callbacks (which could potentially change all kinds of things)? You can do that with Elm (more info here - https://lukeplant.me.uk/blog/posts/two-experiences-with-elm/ ), due to The Elm Architecture and everything being immutable.

(In theory you could do this in TypeScript, but it would be a lot of work and its reliability would depend on everyone coding everything a certain, very unnatural way, with no help from the compiler).

I'm using Elm in production, version 0.18, it is an extremely robust way to make front end code. You just don't have runtime issues.

However, like IBM folks (mentioned in another reply) who said in the their post they didn't know how they would upgrade to 0.19, I also don't know how I will be able to upgrade. Specifically, 0.19 adds some cripple-ware restrictions (you can't use native modules unless you are contributing to certain projects). So, if you want to use something like Intl - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... - not only is there no wrapper provided, the restrictions in 0.19 attempt to stop you from writing your own wrapper. Only the core team can do it, which requires them having both the expertise and motivation to do so. Plus Elm has essentially a closed-source development process. In fact, there is no 'process' for contributing, and the fact that there is no process is deliberate, as far as I can tell.

So for me, if I can't find a way around the restrictions, they may kill my ability to being able to keep my code nicely architectured (i.e. using The Elm Architecture). I may be forced to switch to something like ReasonML with bucklescript-tea - https://github.com/OvermindDL1/bucklescript-tea

I think most of the Intl api could work reasonably well with ports and custom elements. The formatters in particular, which make up most of the API, would probably work quite nicely as custom elements. It's really only string comparison that I can imagine needing ports for, outside of some particularly unusual use case.

You don't need to choose bunch of frameworks and spend hours getting them work together. Elm basically provides the perfect language and abstractions for building UI.

Am I missing something or are most submissions here mostly small landing pages and small form examples? Are there some more complicated CRUDdy showpieces?

We've been using Elm in production for https://halogen.tv and has been a great experience overall.

The codebase is around 60k LOC for the front-end and we've settled on a few patterns that help with reusability and managing complexity.

- We have moved to a very flat architecture where most things are at the top level of the state tree

- We use web components to wrap up things that are a pain in Elm (like exit animations, fancy text editors, interop with various JS libraries)

- Our reusable components take Configs so that the components are not tied to one Msg type, different pages have to provide hookups for those messages but it allows us to reuse components on different pages pretty easily.

Refactoring with confidence is possible! I have worked on large React/Angular apps where it was nigh impossible to refactor something without breaking a bunch of others things (often without a way to know they are broken aside from a full regression test). Typescript has improved things quite a bit, but it can't give you the same guarantees as Elm can.

As for difficulties we've run into:

- The virtual dom diffing slows down as the number of nodes grows, for our live chat we can have thousands of people chatting at once and diffing between the previous/next set of nodes can easily exceed the time we have for the next frame. We've taken to reducing the scrollback available in chat, virtualizing the list is another option.

- The time-travelling debugger is cool to show off but has some limitations that make it less useful in practice. If the Msg is long it gets cut off and there's no way to see the whole thing. There's no way to exclude or filter messages, if you have timer running the message list quickly fills up and it is difficult to find the Msg you want.

- When we were on 0.18 compile times were a large source of frustration, we ended up using a forked version of the compiler to improve things a bit, I wrote about it here https://medium.com/@antewcode/faster-elm-builds-e0669580ee67.

- There is little published information on what is coming down the pipeline, timelines for bug fixes, features, etc

This final one hasn't been a big problem in practice, but the prohibition on effect managers and native code in the community leads to teams all over the place reimplementing the same thing (e.g. interfacing with LocalStorage). It has never been possible to publish code using ports or native code to Elm's package manager, which I think is a good thing, but 0.19 also removed the ability to compile them locally without forking the compiler. I think I am in a very small minority in the community that thinks that effect managers are not evil and can be used for good.

I remember hearing Facebook was using it for Facebook Messenger.

You're thinking of ReasonML, not Elm

Anybody have opinions between the two? If you already know OCaml are there strong reasons to consider Elm instead of ReasonML?

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact