My thoughts on Ash

I want to open this thread for you all to discuss and help those who really like Ash but are still hesitant to use it in a real project. I chose Ash for my SaaS that I’m currently developing, but then I decided to abandon it. So here, I’m going to share with you why I made that decision and a little about my opinions about the Ash framework and the Ash ecosystem in general. This post will be a little long, so I ask you to be patient :pray:.

First of all, I want to make some things clear: this is NOT a hate or random critique about Ash! @zachdaniel and all the people who keep maintaining the ecosystem around the framework (Ignite, Ash, AshPostgres, and so on) are like magicians to me. This is really huge, and I’ve never seen anything like it in other languages. Also, the support from Zach is almost instantaneous, so congratulations, guys.

Another important note is that I’m not an Ash expert like the guys who maintain it, but I think the most important point of view for people who maintain the framework is normal user feedback, so I guess my opinions are valid in this sense.

Now, focusing on the title, there’s no better slogan than “model your domain, derive the rest” for describing what Ash is. It’s really what you’ve ever dreamed of: all your web application needs solved in one place. You don’t need to decide about which library to use, check if it’s active or secure; you just plug and play with Ash. I thought it was too good to be true when using it for the first time. You get an amazing and fully featured authorization system (which is something that Phoenix doesn’t give you out of the box), you’ve got authentication, email, soft delete, an admin panel—sometimes it feels like Ash is a perfect SaaS template. And all of this comes with a pretty declarative and beautiful API. But if Ash is so good, why did I quit it?

Well, this is the part where I share some caveats about Ash. Again, this isn’t hate or empty criticism; it’s just my opinion, and I’m assuming that some of these things may just be a “skill issue.” So let’s dive a little into the problems I’ve had with Ash.

Testing

Ash gives me the feeling that it’s useless to test my resources and code in general, and I’ve noticed it’s not very clear how my test designs should look. There’s a lot of discussion around here and in the Discord community, and the documentation only goes so far. In fact, the documentation has very simple examples and resources about testing, and it gets worse when it comes to the main extensions such as AshAuthentication.

Example scenario: Let’s suppose that I’ve set up my User resource with magic link only authentication. What’s the proper way of testing this? Should I even test it? I won’t be testing the framework, will I? What about the policy which checks AshAuthenticationInteraction? Is it good practice to disable it for almost every test?

Also, coverage is a useless metric to define code safety/quality with Ash, since things only run at compile time, so your resources will always remain with 0% coverage.

Learning Curve

I won’t focus a lot on this topic because it depends a lot. I found it easy to do things with Ash, but I spent too much time in the documentation or reading source code, mainly from AshAuthentication. It reminded me of when I first encountered the devise gem in the Rails world, and it also reminded me of José Valim talking somewhere (I think it was during the development of phx.gen.auth) that Devise was a mistake because things just got too magical. I felt this a bit with AshAuthentication. I think there’s a lot of work that could be done in the documentation to solve this, but the code is really understandable. About Ash, I think it’s just a matter of time until you get the hang of things, but it’s kind of boring to open the documentation every time you want to do a preparation, change, or calculation. Again, it could be a skill issue on my part.

Keeps you away from Elixir

I’ve seen too many comparisons between Ash and Ecto, but unlike Ecto, Ash is not a library; Ash is your application. Your entire app will literally derive from it. You cannot decouple Ash, and it would be a silly thing to do. So you basically need to agree to do things the “Ash way.” You eventually get used to it, but I confess that it bothers me a bit, and I still don’t know if Ash is really for every kind of project—not for technical reasons, but for the necessity of wrapping your business around something. I feel like if Zach wakes up and is no longer in the mood to maintain Ash or to answer my doubts, my application would be doomed. :joy:

With a heavy heart, I’ve decided to follow my reason and remove Ash from my project, but I’m still not 100% sure if the good parts don’t compensate for the bad ones. Maybe this thread will give me another perspective. I would be grateful to have a healthy discussion here with those who are using Ash in production, those who maintain the framework, and those who like it a lot, like me, but are still hesitant to use it.

Thanks again to @zachdaniel and all the community for the great work (including myself, as long as my 2 contributions to Ash count :joy:), and please keep doing the great work on it. This is probably the longest post on the Elixir Forum, so sorry about that, guys, but it was for a good cause :joy::pray:

23 Likes

Thank you for your feedback! I appreciate the kind words :slight_smile: I won’t personally “argue” with your takes really insofar as “convincing” people to use Ash coming from me has a pretty clear bias, but ultimately Ash isn’t a fit for every person or every project and that’s All Good™ :heart:

If you do end up switching your app off of Ash, please do come back with a retrospective, as I imagine that you will have lots of learnings from that process. Best of luck! :hugs:

20 Likes

They’re all really good points!

The learning curve is definitely the biggest one, IMO. It’s a lot better than it was, and getting better every day, but we still have a long way to go. There’s one book out, another on the way, a series of blog posts and tutorials, and more are coming. I guess that’s more of a ‘watch this space’ (and we can’t clone Zach unfortunately, we’ve tried).

The testing one is interesting because I think people expect more from Ash than you really need. Ash provides some tools for things like data generation and property testing, but the rest is exactly the same as you would test in any other Elixir app (or Phoenix if you’re using Phoenix). Test inputs and outputs to functions, test side effects, test UIs. Nothing really Ash specific there at the moment, but the space is evolving (the generators in particular got a lot of polish when it came to writing the testing chapter in the Ash Framework book.)

To answer the specific questions:

The generated code is now your code, so you own it - you can test as much or as little as you want to be confident that it does what you expect. There is no right or wrong way to write tests. If you want to write a couple of LiveView tests that hit the sign-in page and ensure that a user can log in, and be done with it, that’s fine. If you want to test every single generated action, that’s fine too. If you heavily customize the generated actions, not just tweaking the config for the extension, that might be worth testing.

I mean I wouldn’t do it :sweat_smile: But then again, I wouldn’t go to the level of testing the actions in a User resource. I’ve written tests for the Tunez app (used in the Ash Framework book) that is probably as granular as I would go for basic authentication. I have apps in production that have more, I have apps in production that have less!

It is a really big mental shift to think about things in “the Ash way”. But honestly, I’ve been using it for long enough that I don’t think I would want to go back to building apps without it (despite all the pain it still sometimes causes). It’s a big investment, and if it’s not one you want to make, that’s okay! Keep it in mind and maybe revisit it and the story will be better in the future :smile:

9 Likes

I did some contributions recently but I’m no expert, nor do I have production apps built in ash under my belt.

Keeps you away from Elixir

While working on and with Ash I don’t find it keeps me away from Elixir.
I can see how Ash is Elixir. :eyes: Don’t let the declarations fool you, it’s functions all the way down. :joy:

and I still don’t know if Ash is really for every kind of project

I think ash’s impact and significance correlates with the scale and complexity of a project, bigger the project more it matters. That’s my opinion. Like I said, I have no evidence to back this claim. :sweat_smile:

That said, your decision sounds valid, as does your criticism.
Maybe you’ll come back to ash after you built some apps without it.
You level up, documentation levels up. We all level up! :muscle: :level_slider:

3 Likes

By the way, I didn’t express that clearly earlier. What I meant to say is that Ash moves you away from the typical Phoenix generator workflow, like using functions such as Projects.create_project and Projects.list_projects. I understand that I can replicate these functionalities using Ash’s actions and definitions, but it still feels significantly different from the ‘standard’ Phoenix approach that I’m accustomed to

And about this, i forgot to mention but i don’t know how easy to have a team working with ash, talking about learning curve, really curious about it, but thanks for your answer and collaboration.

1 Like

I’m really interested about this book, can i ask you a question, if i buy the current beta version in book i receive updates later or i’ll need to buy the book again ?

1 Like
1 Like

I think a big challenge that Ash (and maybe Elixir to some extent) is that you won’t really appreciate the complexity that it reduces until you’ve built the software for awhile.

For example, if you’re starting out building a simple Task management system, using Ash might seem like total overkill. It’s much easier to keep things in a context file and go from there. The Ash learning curve doesn’t seem worth it at this point, so it’s easier to throw in the towel and stick with traditional context/Ecto statements.

Once the app grows, the idea is that as you need to add more functionality (like, an external Json API), then the advantage of Ash becomes apparent, because you just add an extension and a handful of configuration and you’re done.

I really hope that the learning curve problem is able to be overcome, and I’ve found that the generators (and the Ash book!) have helped a lot with that. I’ve tried Ash a few times in the past and wasn’t able to get over the curve. With the Ash book comes a more guided story/experience, and along with the generators it was finally able to click for me.

6 Likes

100% agreed! I’ve bought the book after Rebecca’s reply and I’m already reading a lot. @sevenseacat and @zachdaniel i have a suggestion that you may have already considered: please include some sections focusing on Ash internals, like a deep dive into Ash, Spark, and other related components. I think this would be very helpful for us to understand the ‘Ash magic’ and even encourage more contributions. Regarding the book itself, it’s a great read! Congratulations again!

6 Likes

Early adopter here (with great help from @sevenseacat, @jimsynz, @zachdaniel & @joshprice). You can go a very long way with a very small team once you get a handle on Ash & how it works. There are always tricky bits - e.g. our initial RBAC & workflow implementations - but these days I’d say we spend the vast majority of our time on UI design & polish as the engine room (business rules, policies, migrations etc) pretty much look after itself.

To the point @mike1o1 made - whether the investment to learn is worth it depends on what you’re building.

2 Likes

Counter to other replies here, I have very little experience with Ash though from what little I do know:

sounds like you just aren’t using code interfaces? These simply write the context functions (in Ash, domain functions) for you, abstracting away the extremely boring and repetitive patterns of params → authz → changeset → manipulate changes → populate virtual fields (on every public function) → etc → return → side effect. The beauty (again speaking as someone who just scratched the surface) is that Ash’s escape hatches aren’t even codified, they’re simply: just write the function for yourself.

5 Likes

We really would love to do this but ultimately we are constrained by how long the book would have to be to go into all of that :sweat:

But that kind of content would be great to get into once the book is out, either as blog posts or docs pages in the framework’s docs.

7 Likes

Yeah, totally, but still would be great to have some blog posts or any other resources who dive in Ash internals, i think would clarify a lot of things and might reduce this “hard learning curve” impression, looking forward to code contribute with Ash someday, i’m loving the book, i think it’ll make myself regret my decision to give up Ash :joy:

3 Likes

I would love to see an internals section in the documentation.

1 Like

I don’t want to be that guy but “sounds like a skill issue”.

You write that it “keeps you using functions like create_project”. These functions are basically just examples. If you feel strongly about it you can write a function like that in any ash domain and it would work.

At work we use DRF (Django rest framework). It’s a little similar to ash (but much worse). Two years ago the maintainers decided that it’s perfect and disabled issues and discussions on GitHub due to “social DDOSing”. However, DRF gives us so much that we need to stick with it. So any time you choose to depend on any type of software you run this risk.

1 Like

I believe that particular point isn’t accurately described as a ‘skill issue.’ Rather, it reflects a difference in workflow compared to my established Phoenix practices. In Phoenix, you utilize generators to create a standardized context structure, and then you customize it by writing plain functions. Ash, in contrast, centralizes everything within resources using a DSL that permeates your core business domain. This represents a significant shift, which is why even experienced Elixir developers sometimes struggle to ‘grasp’ Ash initially. You essentially need to adapt to a new DSL and a different paradigm.

While I acknowledge that this isn’t necessarily a ‘caveat’ in the negative sense, and I agree that saying ‘Ash keeps you away from Elixir’ was perhaps an overstatement on my part, it undeniably diverges from the ‘Phoenix context workflow.’ That’s why using Ash felt weird to me initially. Thanks for give your opinion by the way mate :wave:

4 Likes

You are, of course, right in the way that Ash has it’s own DSL. That is the entire point of Ash.

Phoenix contexts are largely a convention. They aren’t enforced in phoenix in anyway. You can just as easily do things in a Liveview that you would ordinarily do in a context. Phoenix doesn’t try to force you into a right way. It is very different to Rails as an example or Django Rest Framework which very, very much want you to do stuff a certain way and otherwise you are in a world of pain.

Similarly, Ash doesn’t really tell you what to do where. You can pass an Ash Resource to MyGreatBusinessDomainContext and do stuff with it. There is no magic here.

Once you have writte enough applications you realise that every application does the same stuff. Fetch some data, provide some filtering and sorting on it, run some authorization on reading and writing actions, etc. Ash gives you a fantastic DSL to do this in a declarative way. That is what it is all about. Of course I can implement this all by myself in my vanilla contexts but I will, inevitably, re-invent the wheel and simply try to do what Ash does better anyway.

5 Likes

Ash has a lot of features that can sometimes speed up development, but it isn’t for everyone or every team—largely because it comes with significant drawbacks that aren’t immediately obvious. For context, I’ve been programming for over a decade, I’ve used Elixir for about eight years, and I’ve been working with Ash on a daily basis for the past four months.

In my opinion, viewing Ash as just another framework is misguided. While I don’t want to get mired in the “What is a framework?” debate, a good framework provides a supportive structure without imposing rigid constraints on how you build. Phoenix illustrates this well: it suggests a broad outline but lets you shape and even deviate from that outline however you need. Ash, on the other hand, feels more like its own language—a comprehensive DSL that’s powerful but also highly opinionated. Often, it feels like a straitjacket: you don’t fully realize how it limits you until you attempt something ordinary and run into cryptic errors. It’s also unclear when and how you’re supposed to deviate from “the Ash way,” which isn’t well documented.

This dynamic reminds me of my experiences with front-end frameworks: Vue and React. I like Vue because it provides a skeleton and guidance but mostly stays out of the way—you’re still basically writing JavaScript. In contrast, React is always in your face, and straying from “the React way” can be painful. In that sense, Vue is like Phoenix, and React is like Ash.

My team recently began to “Ashify” our codebase at work. Initially, I was open-minded, especially since it was pitched as a way to reduce our tech debt by standardizing common operations, but once I built a new feature with it, I realized it drastically reduced both my productivity and my enjoyment of programming. I’m not the only team member who feels this way. The extensive “magic” also brings Rails to mind, which I used early in my career but left for Elixir. In fact, coding with Ash doesn’t really feel like writing Elixir at all, given that the DSL seems to be heavily macro-driven. For a rough (and admittedly unscientific) comparison, the Phoenix repo has only 19 defmacro statements, whereas Ash—around the same size—has 62. That’s disappointing, especially since one of Elixir’s guiding principles is to use macros sparingly:

Even though Elixir attempts its best to provide a safe environment for macros, most of the responsibility of writing clean code with macros falls on developers. Macros are harder to write than ordinary Elixir functions, and it’s considered to be bad style to use them when they’re not necessary. Write macros responsibly.

Elixir already provides mechanisms to write your everyday code in a simple and readable fashion by using its data structures and functions. Macros should only be used as a last resort. Remember that explicit is better than implicit. Clear code is better than concise code.

Or, as computer scientist David J. Wheeler put it, “All problems in computer science can be solved by another level of indirection, except for the problem of too many layers of indirection.”

Yeah, in my experience this is broadly one of the primary criticisms of Rails more broadly: the magic is great when you’re first starting a project because you can move at what feels like light speed, as a lot of common and generic stuff like sorting, filtering and pagination are included. Eventually though you find yourself having to actually know and think about what is going on under the hood, and having to deviate away from the “Rails way”, and complexity skyrockets and the cognitive load becomes too much.

By way of constructive criticism, Ash’s documentation could stand significant improvement. It often feels auto-generated, with crucial details added as an afterthought. Maybe I’m spoiled by Elixir and Ecto’s excellent docs, but it’s not encouraging when my teammates say, “The docs aren’t clear, but check the Ash book instead.” I’ve also sought help on the Elixir Slack’s Ash channel, only to be advised to join the Ash Discord, which itself is separate from the main Elixir Discord. This is both puzzling and somewhat emblematic of my broader point that Ash feels more like its own language. :slight_smile:

3 Likes

To address the point on support: we provide free support pretty much everywhere including in the elixir slack and here. I’ve only advised joining the discord because there are more people there (by their own choice) who may be able to help. We’ve also answered hundreds of questions here :slight_smile:

We are gradually improving our docs (would hardly call docs an “afterthought” but there is room for significant improvement 100%).

If you’ve ever felt truly limited by Ash please bring those things up to us. It may highlight improvements that can be made, or it may highlight misconceptions on your own end that can be cleared up.

8 Likes

I mean, that’s better than the alternative of “the docs aren’t clear, and now I’m totally stuck.” Yes there’s room for improvement in the docs, but different people learn in different ways and perfect should never be the enemy of good. It’s a work in progress.

(The process might also be quicker if you told us where you got stuck, or contributed improvements back so everyone could benefit.)

6 Likes