# \[ANN\] Makie v0.24

**URL:** <https://discourse.julialang.org/t/ann-makie-v0-24/130207>\
**Category:** Package Announcements\
**Tags:** plotting, makie\
**Created:** [June 25, 2025, 3:48pm UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207 "2025-06-25T15:48:04Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [June 25, 2025, 3:48pm UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/1 "2025-06-25T15:48:04Z")

</div>

**Makie v0.24 is finally out!**  
This release features a large refactor of the internals, replacing Observables with a ComputeGraph. This helped us achieve major performance improvements, better handling of multiple attribute updates, and improved correctness and maintainability.

 ![image](https://global.discourse-cdn.com/julialang/original/3X/3/a/3aed0fa39ca826c7226781bb69cd61e753af9484.png)

This has been a huge effort due to Observables being so tightly integrated with everything. Note that Observables are not deprecated – we just avoid them in the internals going forward!

Read all about it in our blog post:  
[https://makie.org/website/blogposts/v0.24.0/](https://makie.org/website/blogposts/v0.24.0/)

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [June 25, 2025, 4:43pm UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/2 "2025-06-25T16:43:01Z")

</div>

Thank you for the update @sdanisch. Very impressive numbers!

From the viewpoint of someone interested in custom recipes, is there anything we can do to benefit from these performance improvements? Is there a _simple_ example where a custom recipe implemented in terms of Observables is rewritten in terms of ComputeGraph?

I really support the idea of moving away from Observables.

---

<div class="post-metadata">

**Author:** ![Larbino1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/larbino1/32/37831_2.png) [@Larbino1](https://discourse.julialang.org/u/Larbino1)\
**Post date:** [June 25, 2025, 4:44pm UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/3 "2025-06-25T16:44:27Z")

</div>

This is great! If I have written code that uses recipes and observables, will it continue to work?

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [June 25, 2025, 5:16pm UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/4 "2025-06-25T17:16:07Z")

</div>

That depends on the way you’ve been using attributes. If you’ve only been creating observables and passing them directly as arguments to inner plotting functions, that continues to work (even though it doesn’t make use of the lazy graph features). But if you were doing something with `Attributes` that was treating them like a dict, that doesn’t work anymore. Like `plot!(parent, args...; kwargs..., parent.attributes...)` or `attr = copy(Attributes(plot)); pop!(attr, :removed)`, and others that the blog post spells out.

---

<div class="post-metadata">

**Author:** ![Larbino1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/larbino1/32/37831_2.png) [@Larbino1](https://discourse.julialang.org/u/Larbino1)\
**Post date:** [June 25, 2025, 5:23pm UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/5 "2025-06-25T17:23:40Z")

</div>

Thank you. I will read the full blog post! This seems like a big improvement compared to the observables machinery. But I am glad compatiability seems mostly intact.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [June 25, 2025, 5:27pm UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/6 "2025-06-25T17:27:31Z")

</div>

One way is to compare recipes that have been converted inside of Makie, although they are not structured didactically.

For example, rangebars/errorbars in [v0.23](https://github.com/MakieOrg/Makie.jl/blob/f06b9848530058300363513a1bccc2ba01f19d3b/src/basic_recipes/error_and_rangebars.jl#L203-L257) vs [v0.24.1](https://github.com/MakieOrg/Makie.jl/blob/43626fe4de45ef7528b3785788c06144bba9fbff/Makie/src/basic_recipes/error_and_rangebars.jl#L169-L200). It’s not an exact correspondence but you can extract some patterns, and look at other recipes of course. Not all have been converted, yet, though.

Implementation of recipes with many corresponding attributes (that should share an array size, mostly) is much easier because you don’t have to think about order of observable triggers anymore. Instead, you know that the whole graph you construct will be updated in one go for a given frame.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [June 25, 2025, 5:31pm UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/7 "2025-06-25T17:31:05Z")

</div>

> [@Larbino1](#):
>
> But I am glad compatiability seems mostly intact.

Care was taken to leave as many “simple” use cases intact as possible. But from experience we also know that Makie suffers a lot from Hyrum’s law:

> With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviours of your system will be depended on by somebody.

(No pun intended with the “observable” 😉 )

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [June 25, 2025, 5:47pm UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/8 "2025-06-25T17:47:16Z")

</div>

@jules we adopted the following code pattern in our recipes:

1. Access attributes with `plot[:attrname]`
2. Derive new observables with `@lift`
3. Sometimes access the contents with `attr[]`
4. Forward the new observables to the next recipe

I wonder if the following example would benefit from a rewrite:

> <https://github.com/JuliaGeometry/Meshes.jl/blob/12a737f78961de16927968e2694004d65e36eeec/ext/grid/cartesian.jl#L5-L55>

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [June 25, 2025, 6:04pm UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/9 "2025-06-25T18:04:01Z")

</div>

If I have GLMakie (v0.11.5 for instance) as dependency of a package, what exactly should one expect from (or do to get) this update? I’m confused by the version numbers here.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [June 25, 2025, 6:32pm UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/10 "2025-06-25T18:32:50Z")

</div>

GLMakie is its own package but due to the monorepo structure it’s not as easy to see the releases on github as for Makie.jl. You can check the project.toml directly to see what the current version is [Makie.jl/GLMakie/Project.toml at master · MakieOrg/Makie.jl · GitHub](https://github.com/MakieOrg/Makie.jl/blob/master/GLMakie/Project.toml)

So currently its GLMakie 0.13.1 with Makie 0.24.1 so that would suggest 0.11 is from Makie 0.22 as the minor versions have been updating in lockstep for a while.

---

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [June 25, 2025, 9:01pm UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/11 "2025-06-25T21:01:52Z")

</div>

1-4 should all still be supported, unless you explicitely type something as an observable.  
The linked example doesn’t look like it would be helped a lot by moving to the new api, since it’s mainly 1:1 😉  
It would help with having less going back and forth between observables and the compute graph.

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [June 25, 2025, 9:10pm UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/12 "2025-06-25T21:10:13Z")

</div>

If you have any suggestions to improve the back and forth, please feel free to share. It is not clear to me what you mean by that.

---

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [June 25, 2025, 9:22pm UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/13 "2025-06-25T21:22:11Z")

</div>

if you follow the upgrade guide in the blogpost, you’ll create less observables on top of the compute graph 😉

---

<div class="post-metadata">

**Author:** ![hz-xiaxz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hz-xiaxz/32/209585_2.png) [@hz-xiaxz](https://discourse.julialang.org/u/hz-xiaxz)\
**Post date:** [June 26, 2025, 7:44am UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/14 "2025-06-26T07:44:12Z")

</div>

I’m curious about whether this refactor has some improvement on precompiling? Or somehow making it worse? (new ComputeGraph linking etc.)

---

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [June 26, 2025, 8:37am UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/15 "2025-06-26T08:37:57Z")

</div>

Sadly it made it a bit worse.  
We still hope to reclaim some regressions and maybe even improve over v0.23, since in theory it could work pretty well with precompilation and we haven’t put as much time into it yet as we did for Observables.

---

<div class="post-metadata">

**Author:** ![hz-xiaxz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hz-xiaxz/32/209585_2.png) [@hz-xiaxz](https://discourse.julialang.org/u/hz-xiaxz)\
**Post date:** [June 26, 2025, 8:44am UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/16 "2025-06-26T08:44:23Z")

</div>

☺ Got it! Thanks for the effort.

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [June 26, 2025, 6:15pm UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/17 "2025-06-26T18:15:50Z")

</div>

Always exciting to see Makie getting better-still!

But I’m afraid I’m still struggling to understand how to use the new the `ComputeGraph` system. The examples in the blog post are too incomplete and abstract for me. They have a variable called `plot` (which seems like a spicy choice given that it shadows an exported function) and it seems that `plot.attributes` is of special significance. But what is `plot` and where does it come from? Context would suggest it’s a `ComputeGraph`, but there are no examples of how to instantiate one.

My main use of `Observables` thus far has been to do things like update the datapoints in a `scatter` over time, adjust the axes of a figure, or change the contents of a `Label`. How can I connect those uses to the new system?

I found [Observables | Makie](https://docs.makie.org/stable/explanations/observables) (plus some blog posts) helpful back when I was first using Makie. That page now makes mention of the new `ComputeGraph` stuff, but could that be improved to a link to a full page that provides a similar level of detail?

_EDIT:_ it looks like the Lorenz demo on [Welcome to Makie! | Makie](https://docs.makie.org/stable/) has been updated and provides a usable example. I guess I can probably piece it together from there.

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [June 26, 2025, 8:41pm UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/18 "2025-06-26T20:41:18Z")

</div>

We just call the objects created by recipes “plots” in our imprecise language so that’s why the variable in the example is called that. If you’re only plotting by passing observables to existing plotting functions, you don’t need to interact with the compute graphs inside at all. The one thing worth learning in that scenario is to use the new `update!` function to update multiple attributes of a plot object at once, so you can make sure array lengths never go out of sync, for example when GLMakie renders a frame in between two of your observable updates.

Other than that the other compute graph functionality is mostly for people writing recipes. It’s much easier to add new nodes to the graph than setting up a network of observables and getting that to sync correctly, at least for more complex recipes. `plot.attributes` is actually the graph, I complained about that, too, as it’s a little confusing that it’s not an `Attributes` dict anymore like it used to be but kept the name.

---

<div class="post-metadata">

**Author:** ![Jake](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jake/32/46007_2.png) [@Jake](https://discourse.julialang.org/u/Jake)\
**Post date:** [June 26, 2025, 8:55pm UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/19 "2025-06-26T20:55:03Z")

</div>

I have not yet tried it, but wondering if this performance increase will help with low powered machines with poorly implemented OpenGL, like the Raspberry PI family of computers.

---

<div class="post-metadata">

**Author:** ![stene](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stene/32/26044_2.png) [@stene](https://discourse.julialang.org/u/stene)\
**Post date:** [July 17, 2025, 6:44am UTC](https://discourse.julialang.org/t/ann-makie-v0-24/130207/20 "2025-07-17T06:44:48Z")

</div>

Probably not. I have an idea to port CairoMakie to [Skia.jl](https://github.com/stensmo/Skia.jl), since Skia can support EGL and Vulkan. I hope [sdanisch](https://discourse.julialang.org/u/sdanisch) thinks it’s a good idea.

[Next page](https://discourse.julialang.org/t/ann-makie-v0-24/130207.md?page=2)
