For most people, the standout change here will be the addition of `config/runtime.exs`, which is SUPER exciting!
Before, runtime configuration was only available in “releases”, which is Elixir’s packaged tarball for deployments. All other configuration was compile time only. However, running your app locally in a development environment through `mix` would technically compile the app, so even though you didn’t have runtime config, it “felt” like runtime.
Because of this special feature of releases which had their own (and the only) runtime config, you often had to duplicate your config in the runtime config file and the regular compile time config file (for outside releases).
Now, with this new addition, there’s one unified place where ALL runtime config is defined, and which supports runtime config in ALL the different ways you run your app.
To me, this is a huge UX improvement for Elixir devs!
> To me, this is a huge UX improvement for Elixir devs!
That's awesome, I have a module that is a helper to inject data in a socket to use with liveview but the data that I need isn't present in the dev environment and mocking it is annoying because if I use Mix.env the code in the release breaks, being able to pass an ENV var and just check it to decide to mock it or not will simplify a good amount of code.
Is Elixir really the general purpose productivity tool that comments here (and on other HN posts) make it out to be?
I've loved playing with Erlang and Elixir. The concurrency model and approach to failure are fascinating and clearly powerful for certain problems. Elixir's Pheonix feels as productive as Rails. I've read most of Joe Armstrong's books and watched most of his talks.
However, I feel like I can throw my daily driver programming languages including Go, Ruby, Rust... even Haskell at any problem and give or take performance, come out the other end with high quality software at scale.
When I last wrote Elixir, it felt great when I was doing basic Rails shaped work or lower level concurrency heavy networking (I was playing with TUN/TAP interfaces), but I really can't imagine it as a general purpose programming language.
For example I can't imagine scripting in Elixir, but I can and do in the other languages mentioned above. Also I remember trying to write a parser library and it felt way more verbose and unmaintainable than the equivalent Haskell or Rust.
This is hand wavy, but does anyone feel what I'm getting at? Any thoughts?
I don't think Elixir aims to be a general purpose scripting language. I only use it for hobby stuff, but lately I've been writing my scripts in a few languages to compare their characteristics: performance, lines of code, and delta code change when making a single threaded script into multi threaded.
I find that Elixir code for these tasks tends to be a bit longer than standard scripting languages, a bit shorter than Go/Java, with performance around Go and slightly better than Java. One of the interesting things I find though is that with the Flow library, bringing it from single to multiple threads tends to require fewer changes - generally I just have to change some uses of Stream to Flow and I'm up and running with a solution that's using all my cores.
That'd be about my assessment as well, though it's been a while since I programmed Java/C++ etc. I ported Vault's Shamir secret algorithm from Go to Elixir, and it was about 25% less lines of code. Though Python scripts tend to be shorter for small projects, bigger ones get more verbose when dealing with classes and data sharing, IMHO. Python scripting is also more prone to difficult debugging issues due to immutability and inconsistent/dated libraries. For example, a Python SPI library I tried for an IoT sensor deleted all of the items from the list of SPI bytes given to it... which took an hour to figure out as that was completely unexpected and I kept thinking my part was bad (though perhaps I'm too used to Elixir's immutability now).
"Comparison to Flow
You may also be interested in Flow by Dashbit. Both Broadway and Flow are built on top of GenStage. Flow is a more general abstraction than Broadway that focuses on data as a whole, providing features like aggregation, joins, windows, etc. Broadway focuses on events and on operational features, such as metrics, automatic acknowledgements, failure handling, and so on." - (https://github.com/dashbitco/broadway#comparison-to-flow)
> However, I feel like I can throw my daily driver programming languages including Go, Ruby, Rust... even Haskell at any problem and give or take performance, come out the other end with high quality software at scale.
You're probably right. With a very high-level language like Ruby and an extremely efficient systems language like Rust, you've pretty much got the entire spectrum covered. With libraries like Helix, you've even got an escape hatch if you start with Rails and hit unexpected bottlenecks.
IMO Elixir is nearly ideal for web startups due to productivity, enough performance, easy scaling and a very gentle learning curve. If you've already got all those other tools under your belt, then those pluses are probably less of a draw.
It really depends on what you mean by general purpose.
At work we use Elixir for web and data ingestion, and I could have used Ruby for web but Ruby is considerably behind for data stuff.
Elixir is fine for one-off scripts, Ruby and Python may be a bit more convenient, but overall they are all too heavy to distribute compared to languages like Go and Rust.
Elixir is also used for high-end embedded and there is the whole distributed programming bits, which is quite specific to its platform, and more complicated to setup in almost all other places.
So overall it does provide some nice coverage across a couple areas although it lacks on other ones (GUIs, ML, etc).
I've written scripts in elixir that did performance testing of parallel downloads over cloud storage services. Also I have a script that I run once a year year to scrape Google maps for driving mileage.
The deployment story for elixir scripts sucks because it is less portable than say ruby or python (the person running the script needs to have elixir and you can't really use library deps in a sane way), but I don't mind it, because it's totally worth having less hassle for the cases where you want a well-defined deployment.
At work, I am using elixir to: orchestrate VMs (this is more traditional elixir-ish), but definitely not really a website or embedded, as a PXE boot provisioning system for metal systems, as a substitute for ansible for laying out software on systems, which are more script-ish, but on the side of "scripts for which you are really going to want to have a consistent deployment story".
I'd be curious to hear about your experience writing a parser vs Rust. NimbleParsec or just plain binary pattern matching make parsers suer easy to write in Elixir. I wrote a pretty complicated one for an old telecom data exchange format a few years ago and it was a breeze.
I'm in the same place as you. I love using Elixir, but like you it doesn't feel very general purpose to me. I mostly just write Phoenix apps with it though. I went through Dave Thomas' book and it did feel like a mostly general purpose language when going through that, but of course those examples were chosen intentionally. It makes me think I just need to try more often. I'm so productive and fast with Ruby however that I always reach for that for scripts. I really need to buckle down and make myself write a non-trivial CLI tool in Elixir.
Part of what I suspect might make it feel less general purpose is that unless you spend time really learning the internals then it seems somewhat mysterious and constraining. The immutability for example (which most of the time I love) made it a nightmare when I was trying to process and transform deeply nested JSON. I tried a few times in Elixir and just bailed to Ruby where I could directly mutate stuff 5 levels down with ease and efficiency. The code seemed way more straight forward and readable.
How do people deal with things like deeply nested JSON in Elixir? Is there a way to make use of actors to avoid some of the pain points?
As a side note, a common misconception is that updating a large data structure on the BEAM is inefficient because values are immutable, so you have to copy the whole structure to make a tiny change. This is untrue, as Elixir (and Erlang) "maps" are implemented as HAMTs[2], which support very memory efficient updates by "sharing" the unchanged parts between the the old and updated maps.
I think it would be hard for Elixir to replace Python or Go for general purpose CLI tools.
Part of what makes Python nice is it's available everywhere. If you have a zero dependency CLI tool, using Python is nice because you can just run the script straight up. The standard library also has good support for argument parsing. I've written a bunch of little tools to help my daily workflow on the command line. I always reach for Python or Bash depending on what I'm doing. I haven't really seen a compelling reason to switch.
> using Python is nice because you can just run the script straight up.
except when it doesn't work
which happens more often than not
Elixir is not probably best suited for CLI tools, given the BEAM has slow startup times, but people wrote scripts in Ruby, so it might be acceptable for someone
Elixir scripts can be distributed as releases which include the compiled modules bytecode and the VM to run them or as escripts, which are binary executable that can be run on any system with Erlang installed
> New Elixir thread -> nickjj pointing out the superiority of Python or Ruby. Lol!
Not really. He asked a question about using Elixir as a general purpose programming language so I gave my honest advice and opinion on using it as a scripting language based on prior experience.
Instead of cherry picking my replies out of context, why not go through my entire comment history in all Elixir and Phoenix HN threads? I'll guarantee you'll find tons of positive comments.
Here's a couple to get you started after spending 60 seconds searching:
The first two have over 100 up votes combined for reference.
I'm not looking to argue on the internet, but I do find it strange that so many folks in the Elixir community cannot take any constructive criticism of the language in any way. You realize we're all on the same team right? To build kick ass applications that we enjoy building while users enjoy using it.
I see it more like asking questions, offering suggestions and potentially trying to improve the language and eco-system by offering feedback and sometimes even pointing out things that hang me up.
For example, the other day someone asked if Phoenix could ever support similar features of Rails such as having something similar to Rails Application Templates. I thought it was a great idea and it was something I wanted too, so I gave as much feedback as I could around why it might be useful to have.
In the end, it looks like most people don't want such generators, or having an ability to build a community around templates like Rails, Laravel and Python. That's based on only a few people commenting to say it's not a good idea and pretty no one else replying saying they wanted it.
You might see that as complaining but I see that as trying to fight for a really useful feature that will help grow the community and make it easier for folks to build applications in the end.
If I didn't care I would have left the Elixir community long ago. I have way better things to do than troll forums. The project I was gung-ho about developing in Phoenix is no longer using Phoenix because after all of those forum posts and struggling endlessly with Elixir I came to the conclusion it isn't the right technology for me to build web apps in. I continue to sometimes post because I hope one day things will change and I'll try to pick it back up again when the community and eco-system is more mature (from a library selection POV, not personal maturity).
The issue is that there is a gap and if you won’t learn the language nor use it, the gap won’t ever be closed.
For example, you said elsewhere a solution was complicated because it used io lists and a binary constructor but both concepts are explained in Elixir’s official getting started guide. So sometimes it feels you are saying things are complex while you don’t seem to be actively learning the language and some will definitely find that frustrating.
It would be the same if I went to Rust forums, a language I haven’t yet studied in any depth but read a lot about, and constantly said the ownership mechanism is complicated.
Apologies if this comes up as rude. You do seem to be a person open to feedback, so I thought I would drop my $.02.
It's not being able to write what I think is intuitive code and let's be real now. Programming is all about using tools that make you happy and productive. That's why there's so many different viable choices.
For me, personally (opinion of course), I don't want to have to worry about using binary constructors or io lists instead of strings every time I want to work with a string. I just want to use strings. Fortunately other languages can work with strings efficiently so I don't need to concern myself about such optimizations. I can just focus on the business problem at hand.
When stuff like this happens all the time, yeah, it gets frustrating and eventually you decide a tool isn't right for you. I think I gave it a fair shake too. I wrote a pretty big app twice in Phoenix, once with and once without Live View. I even delayed shipping my product for over a year waiting for Live View to get more fleshed out. And even then it felt like I was pioneering things because I kept running into severe bugs (which I reported).
The lack of libraries is kind of the straw the breaks the camel's back. I can maybe get beyond some of the language issues if it lets me be super productive but I found myself having to implement so many libraries myself because there's no official libraries available for Stripe, AWS, etc.. It just lead to feeling like I was spending more time writing libraries than developing my own app.
In time I hope the Elixir compiler could be smart enough to make optimizations for you behind the scenes and maybe there will be more libraries in the future too. In time Live View will get more fleshed out and polished as well, which is always welcome.
I am well aware you know this but Elixir is a different paradigm than Ruby and Python. Approaching it like you could do everything as in Ruby or Python means you are unwilling to learn the functional aspects of the language.
IO lists have useful properties that are not readily available in Ruby and Python, so they come with benefits, and Phoenix uses them to great extent for fast templates.
Binary constructors aren’t optimizations either but the way to construct binaries and strings in Elixir. They’re as fundamental as pattern matching.
The lack of libraries is something I can identify with but please understand it is frustrating to hear over and over again something is hard in Elixir while refusing to learn the language basic concepts because you would rather do it as in Python or in Ruby.
>You might see that as complaining but I see that as trying to fight for a really useful feature that will help grow the community and make it easier for folks to build applications in the end.
The change in mindset you're demanding from the devs is impossible to accomplish through comments I think. You'd need to develop personal real world relationships with the devs to be able to have such an impact, or create pathways for people with this mindset into the community.
It's the mindset of DHH or Taylor Ottwell what makes their product oriented frameworks more product oriented. Core devs and core parts of the community having this mindset is necessary as a fruitful foundation for more product oriented feature requests I think.
> It's the mindset of DHH or Taylor Ottwell what makes their product oriented frameworks more product oriented.
Yeah I totally 100% agree with this. I think it's very much so why Rails and Laravel won't be going anywhere anytime soon. As it turns out most people who are into web development are trying to build products and services.
But I will say that every time I've talked to Jose or Chris (I don't know them personally, I just mean in chat), they always say the best way to offer suggestions or feedback about the language or framework is to post on the forums. It's just unfortunate the community is so against feature requests or open to talking about things.
It just feels like the forums have the same regulars shooting down ideas from anyone new, or feature request threads get little to no replies.
>It's just unfortunate the community is so against feature requests or open to talking about things.
I don't have that impression, but I also got into Elixir knowing that it's not as product focused and more hands on.
For me it was more important that I don't hate the language and programming paradigm I'm mainly using. For purely business oriented stuff or quick MVPs I can still use no-code tools, which in 2020 is really the way to go if you're solo or a very small team.
>It just feels like the forums have the same regulars shooting down ideas from anyone new, or feature request threads get little to no replies.
Most on the Elixir forums seem to be employees and hardcore programmers, not founders and business people. I think even the main devs are employed, this changes how you think about prototyping features or tiem savings if you're never really in that situation and work fixed hours.
I think that the forums are a great learning resource and people seem nice, I mean you can't say that they aren't pacient with you.
No, Elixir does not aim to be a general-purpose language. It is built for a virtual machine that greatly excels at distributed, fault-tolerant systems.
there are degrees of general purpose. I think the point is "more general purpose than just web servers". That it excels at high-end embedded is part of the point. Should you sue it for low-end embedded? Probably not.
I don't think it'a trying to do that. It has its own merits and a number of great use cases. Being general purpose doesn't mean that it needs to compete head to head on cross platform scripting tasks.
When I compared Elixir/Phoenix vs Ruby/Rails to build a web application a few years back, I ultimately stopped using Elixir because the third party libraries superficially seemed to be more immature and not as well maintained.
Most semi-popular RubyGems are in v1.0+, have contributions and bug fixes within the past few months, and have a feeling of community around them. There’s even huge companies like GitHub, Shopify, and Basecamp behind some libs.
Elixir mix packages felt abandoned. Most were in the low digits 0.0.x, no commits for over 6 months, and the docs seemed to have a lot of notes in them that it’s early, not maintained, don’t use in production, etc.
Has this changed recently? Can anybody speak to why the Elixir ecosystem feels more empty?
Elixir/Phoenix feels like Rails back in 2008 when we built one of the largest Rails app. It will take time for the community to develop.
That being said, my company has been using Elixir/Phoenix for three years and while many times there isn't a library for Elixir, often times there is already a stable Erlang library we can use.
We have also changed our habit from looking for third-party libraries to either building our own module which we discovered they are fairly easier to build than we thought, or coming up with alternate solutions that built on top of the powerful Elixir/Erlang technology (e.g. OTP).
Incredible.
Been using this stack for an year and I'm super excited for the future. Lately I also do see multiple new companies picking it up for different workflows and applications.
Though it may not reach Ruby levels of popularity, it's still just fine. Learning curve is favorable, performance is stellar, and the toolkit that comes with the language is quite featureful.
I see other languages borrowing elements from Elixir - especially LiveView and Pattern Matching.
The only hiccups I faced where when I had to roll out my own solutions for a few things (a background job processor, error manager, a mocking module for unit tests, etc.)
Even with all this, I'd still say Elixir is worth it, given the performance gain and the patterns it enforces. It all just makes the code easy and understandable.
Rolling your own tools is an irreplaceable way to learn things thoroughly.
That said, HN readers from outside the Elixir should know there are great libraries for all of those use cases. Point in case is background job processors—we have plenty of options, though I’m especially fond of Oban[0] (full disclosure, I’m the author).
> Rolling your own tools is an irreplaceable way to learn things thoroughly.
I completely agree. It's also a great way to avoid complexity you don't need. There are limits, but especially while learning I like to err on the side of fewer dependencies.
BTW, I just now saw that getoban.pro was a thing. It looks great!
haha, yeah the annoying thing about elixir is that sometimes, you give up, roll your own solution (because it's not terribly hard to do), and then right after you're done, some team has built a slightly better solution (because it's not terribly hard to do).
I've been writing Elixir professionally for a couple months now and I find it fascinating how many tools Elixir gives you to play with.
However, I started a toy project in it and immediately ran into trouble due to its dynamic nature. Printing function arguments to see what they are, runtime errors... Is there a way to get around this besides adding spec tags on everything?
It depends on what you are struggling with. If you want formal type documentation and some decent type checking, Dialyzer is pretty good. That’s really the only solution for Elixir.
I, for one, am hoping that the Facebook solution allows us to implement something in Elixir to interface with it so that we can take advantage of it in Elixir, but that is yet to be seen.
I've been using Dialyzer and it works well enough most of the time. Maybe the Elm compiler spoiled me, but when Dialyzer tells me "this pattern will never match" and not offer me tools to fix it, it's very frustrating. I'm not sure if it's possible, but it would be nice to have an action to autocomplete missing patterns like in Elm / Rust.
Dialyzer messages can be pretty obtuse. Usually I take it as a cue to just re-read the function and it's often somewhat clear where the problem lies due to immutability (not always though).
Another trick I'll do, is to use (abuse) pattern matching:
def foo(%SomeStruct{} = arg, value) when is_integer(value) ...
That also helps Dialyzer narrow down possibilities too and will blow up on runtime.
If you use VSCode, the ElixirLS module will auto-suggest @spec's for your functions.
Yeah the big problems with Dialyzer are that it can be slow at times and that the error messages are not great. However, a lot of the error messages are the same esoteric messages, and you can get used to debugging them when you know what they are trying to call out.
You may get some mileage out of reading up on structural typing, and thinking about how you can apply that to your function heads. You can write several versions of functions that are explicit about the shape and type of data they expect. If you're thoughtful about it, then you'll run into fewer errors.
AFAIK you don't need to add @specs everywhere to get useful warnings from Dialyzer (or Dialyxir) as it does some type inference and also the standard library is already annotated, but I only played with it one time so don't quote me on that.
Fun fact: dialyzer does not use your @spec’s to run checks. If you do provide a @spec, it will check that it matches, but it doesn’t affect dialyzer itself.
Thanks for the great work, I am a big Elixir and Phoenix fan. Although I don't think it will ever hit the heights of ruby or node in terms of popularity, I believe elixir and phoneix are very good long term bets.
The improved Compiler checks are
a great step in the right direction. I know elixir language isn't going to change much (if at all?) now, so putting more time into things like safety and developer productivity will be warmly welcomed.
Worth noting that the concepts of piping and pattern matching don't just exist in the language itself, but also in an architectural level. Plugs, for example, allow you to "pipe" entire web requests in a very elegant and logical fashion.
Couldn't have answered the question better/more succinctly myself.
When I'm working on the JavaScript (front end) side of an Elixir project, I repeatedly get into these positions where I'm thinking, "Man, I could express this so succinctly and elegantly in Elixir. There's no way in JavaScript that doesn't feel clunky in contrast."
That makes sense. For a period of my career I did some Prolog and always liked the way pattern matching allowed you to write extremely descriptive code.
Funnily enough, I think pattern matching is one of the most exciting things to happen in Ruby for a long time. While it isn't on a par with functional pattern matching it's still going to be incredibly useful.
I was just thinking that a language not changing much can be a sign of a very good initial design. Having to change things all the time is often a sign that there is a major flaw in the foundation. Good to see a language that is very active, but refining rather than ripping out the floors.
A talk in ElixirConf this year showed that the pipe operator in Elixir is just a macro. A Code BEAM V conf Q&A with Jose had a (playful, trolling) question about implementing right handed assigns and Jose said that you can just write a macro if you want it. That all reinforces that the core lang doesn't need to change really; it's extensible enough to let you do whatever you want on top. Pretty cool.
jump in! I've been working with it for my startup for the last year and its been a breath of fresh air.
1: phoenix is fast and almost as expressive as ruby (15 ms response times)
2: weird timing bugs don't show up in my code.
3: the tooling is fantastic, a close second second only to rails
4: Ecto beats active record and is easily the best data mapping layer I've worked with. All the nodejs orms I've used in the past felt like clunky toys by comparison.
5: websockets via channels is second to none. seriously, django channels and rails action cable directly copied it but they are not as performant. you can scale a single machine to handle a few thousand connections out of the box and it supports multicluster and long polling to boot.
6: absinthe is great for graphql.
7: live view, think turbolinks on steroids. you can send down updates to the client dom over websockets.
Agreed! On frontend, Phoenix is missing support for component-driven development. LiveView is going that direction, borrowing some react concepts, so I wouldn't be surprised if we saw something like this soon.
The JIT looks exciting, though to be honest I've never encountered any significant performance issues with Elixir in four years of use.
Probably the even bigger quality of life improvement for me will be the improvements in recompliation. Greatly reducing the files to be recompiled when a file is touched should be a nice dev experience improvement when working on projects with large numbers of files.
If you (like me) can't wait for the official release, use asdf to install the master branch. I've been using Elixir 1.11 for a while now and haven't run into any issues!
Is anybody working on (VR/AR) telepresence/fpv stuff with Elixir? (Think of the new Nintendo toys where you control an RC car through an UI on another device). Elixir and a combination of Nerves and Phoenix seems like a good fit for applications like this..
I'd be curious to know if WhatsApp engineers evaluated using Elixir, if they are using Elixir only partially or not at all, and which are the reasoning behind that
Oh, a lot of good stuff in this release! I'm especially excited to be able to pass a map to Logger and have it print `key1=value1 key2=value2`.
I thought Jose had said earlier that Elixir was basically "done" a version or two ago, which I was impressed by; how often is software ever finished? But it looks like we're still getting some juicy functionality nuggets.
This is awesome. I’ve been using Elixir for a long time and the abstractions with BEAM/OTP make it quite a powerful platform. Great additions to the ecosystem.
As an aside, I’ve been playing with Factor recently and it’s been quite the learning experience with concatenative paradigms. I mention it because I was surprised it had erlang-like concurrency models in it (actor, and more).
If you want to host a Phoenix app on AWS I would use a Docker release and then point the DB at RDS. You can run Docker under ECS/Fargate or Elastic Beanstalk.
Seconded. This is what I do, the only exception being that it goes to K8s/OpenShift instead of AWS-specific CaaS offerings.
You can easily treat a Phoenix app like you would a rails app, or you can go full on into releases and ship it like a binary. It's all up to you and whether you value easy production debuggability or simplicity, etc.
Gigalixir is a great experience. Like Heroku you'll pay for it as you scale however. But if you don't want to hire a devops person, it's still probably cheaper than the alternatives.
Elixir looks pretty interesting however lack of static types has held me off from picking it up. Curious what the experience of people with typespecs and Dialyzer has been:
1. How close do you think it comes to static types?
2. Does it have good IDE plugins providing type errors as you code?
If you squint sideways pattern matching on structs plus guards is sort of like type checking (but not really). The map checking mentioned in the changelog will be a nice addition.
I've been doing both a lot of TypeScript (for work) and Elixir (for personal projects) for the last few years and I do get a stronger sense of safety from TypeScript (especially during refactoring) but Elixir feels much more concise and fun to work in and the Phoenix event ticketing app I've been running for the last 3 years has been rock solid.
btw I've been programming for 30+ years with all sorts of untyped, dynamically typed and statically typed languages. I still haven't found "the one true language". Something like strongly typed CoffeeScript that runs on BEAM would be close (I've been watching Gleam for a while and I plan to play with it after it matures a bit more).
We've used Elixir at our company for several years. Overall I've loved it, but I hope some experiments are done with a type system.
(I don't find dialyser that strong in terms of performance and code editor help.)
I think Typescript would serve as good inspiration because (1) it's a type system for a dynamic language underneath (javascript) and (2) it uses structural typing which fits well with pattern matching.
It comes nowhere close, if you are used to programming in languages with static types, the devx is just not on the same level. That being said, pattern matching is very powerful, and gives you a lot of what static types gives you in terms of safety. I’m just to spoiled by the level of productivity I get from editors when using a languages with static types at this point and using elixir full time would feel like taking a step backwards.
By contrast I'd rather not go back to meticulously decorating source files to add types where they aren't needed, so Elixir seems like the perfect language to me.
Somewhere between 20-30% of the way there. In practice (especially with vscode/elixir-ls plugin) in my experience it does fulfill the 80/20 rule, it catches enough errors that the runtime recovers from the remaining ones (type errors do not cause the vm to panic; just your running "green thread will die and get restarted") with no real customer facing issues.
If you need static types because your team has scaled then it's likely inadequate, but I don't have experience with that.
I won't directly answer 1 or 2, but here's my experience.
For my job I was primarily using Elm and Go then for my new job it's been all Elixir. I thought I would miss Elm's compiler (Go, I do not miss).
It's hard to explain, but I find that instead of thinking about what well-defined thing I'm reasoning about, it's about the flow of the data and what shape it happens to be in.
In saying that, with structs and Ecto schemas, we pass those around primarily and pattern match on them too.
Before, runtime configuration was only available in “releases”, which is Elixir’s packaged tarball for deployments. All other configuration was compile time only. However, running your app locally in a development environment through `mix` would technically compile the app, so even though you didn’t have runtime config, it “felt” like runtime.
Because of this special feature of releases which had their own (and the only) runtime config, you often had to duplicate your config in the runtime config file and the regular compile time config file (for outside releases).
Now, with this new addition, there’s one unified place where ALL runtime config is defined, and which supports runtime config in ALL the different ways you run your app.
To me, this is a huge UX improvement for Elixir devs!