How to define parallel states?


If I design states for a minimal app, I will have states like {paid, in stock, not sent} or {not paid, not in stock, not sent} and I can make these multiple events as one like ‘paid_in_stock_not_sent’ and ‘not_paid_not_in_stock_not_sent’ but I will multiply the number of states for nothing. That’s the difference between a toy system and a professional one.


Hey Adrien—Not sure I understand exactly, do you have an example sketch we could take a look at?


Hi Ryan,

you have two ways to model complex states. Let me take an example with a (simple) complex state made of a payment, fulfilment and delivery noted {payment, fulfilment, delivery}.

Option 1 (complicated to model and work with)
You model your complex state as a concatenated big piece

  • payment_not_done_fulfilment_not_done_delivery_not_done
  • payment_done_fulfilment_not_done_delivery_not_done
  • payment_done_fulfilment_done_delivery_not_done
  • payment_done_fulfilment_done_delivery_done

Now my question is “What happens if fulfilment needs to be done before payment?”, you need to add a bunch of new states and it will be super complex to read and your interface will have a multiplication of identical code for each part of the state.

  • payment_not_done_fulfilment_done_delivery_not_done
  • payment_not_done_fulfilment_done_delivery_done

Option 2 (Simpler to work with)
You model your complex state as a collection of individual states

  • payment: [not_done, done]
  • fulfilment: [not_done, done]
  • delivery: [not_done, done]

Now you have it all, each part of the interface is independent and you can model it simply. Here comes my question again “What happens if fulfilment needs to be done before payment?”, then you do
{not_done, done, whatever } and you are done. :grinning:

The implication is that the visualisation on the top right of Sketch needs to be accepting two or more blue parts to model for a complex state.

Is that a bit clearer?



Looks like I killed the conversation… :frowning:


Hey Adrien—You didn’t. :slight_smile: Kevin’s kicking around an implementation of parallel states that may help your use case. He’ll announce it here on the forum when it’s ready, so stay tuned.


Awesome! :yum: Will be testing it straight away.



@Adrien, @elijah-schow, and @jeremyfourna — I’m implementing parallel states and working through some of the tricker parts right now.

Before deploying, I’m curious to get ya’lls opinion on two things:

  1. Syntax for specifying parallel states. I have something in mind, but would like to hear about what ya’ll think first so we can have some discussion before committing to one. E.g., should it be a prefix/suffix in the name? Some annotation indented within the state? etc.

  2. Parallel states can lead to unclear semantics. For example:

    foo -> A
    foo -> B

When C1 and C2 are simultaniously active and the “foo” event shows up, where does the statechart end up?
Or is this kind of configuration an error in the first place and should be disallowed?

There are lots of situations like this, and I’m curious to hear if ya’ll have any other examples or thoughts.



To me C1 and C2 are independent.
If C1 is active and foo happens then A disregarding C2.
If C2 is active and foo happens then B disregarding C1.

That’s what I meant by “The implication is that the visualisation on the top right of Sketch needs to be accepting two or more blue parts to model for a complex state.”

Currently, I describe how to go from a state to another. All the rules for active states are active as well. So the syntax should not be different. If I take the boring shipment example again.

    Paid -> Banked
    Packed -> Wrapped
    Sent -> Shipped

Right now the * 2 and 3 are ignored so the state is {Money_out} when it should be {Money_out, Undone, Stalled}. It allows thinking of 3 parts of the interface independently without to make different sketches. Because, you can ship before you pay, or send before you packed (and that’s wrong) even if you didn’t think of it beforehand. It makes a more robust interface.

I have another use case, but that may be a bit more advanced and not everybody would need it, although it should not be massively different.

      Parallel_Action -> B
      Parallel_Action -> C

On Parallel_Action state goes from {A} to {B, C}

Here you got another too long post.


The implicit root state of the statechart is a regular state, a disjunction where exactly 1 child is active.
If we discard this rule (i.e., follow both transitions from C1 and C2 to make both A and B to be active), then we would no longer be in the realm of statecharts as defined by Harel in his original paper.

I’m not saying that statecharts are the best way to model every system, but for the purposes of I think it’d be best to stay with that well studied notation rather than inventing our own semantics — there are several books about statecharts, a good SCXML reference spec for implementors, visual modeling tools, etc.

Do you have suggestions about the parallel state situation I brought up that work within the existing statechart semantics?

One option could be to transition to “A” because that transition occurs first in the textual order (the approach SCXML takes)?
Another option would be to reject the spec for being ambiguous.


I’ll be honest, I won’t take the time to read the hundreds of pages you referenced, my job is elsewhere.

Let me just say this: “SQL” is a well known semantic, but every single vendor have its own “dialect” of it with extensions for unique functionalities that the standardisation body didn’t think of. The semantic you have doesn’t allow any 1 to many (state or transition) so no, this semantic doesn’t work unless you build crazy “option 1” states like described in an earlier post.

I understand you want to follow strictly the standard because it is easier. Fine with me, no hard feeling, I’ll continue with my own tools in order to build systems that can have complex states. They are not as rich but they are easy to work with. I guess I’ll need to work on a visualisation.
I’ll check this space every now and then to see how you guys progress.

Have a nice time.


I would also find this feature incredibly useful.

Here’s a simplified use case of a Control Panel, where I’d like to represent in parallel what is ‘Sorted by’ and how much is ‘Zoomed’. In this case I’d like to be able to identify Sort and Zoom as ‘parallel states’, so that their child states can be active side by side.

I could imagine representing this by prefixing the parallel states with a special character, for example:

Control Panel
    Sorted by Date
      sort by title -> Sorted by Title
    Sorted by Title
      sort by date -> Sorted by Date
    Zoomed In
      zoom out -> Zoomed Out
    Zoomed Out
     zoom in -> Zoomed In

This particular use case doesn’t directly clarify your 2nd point @kevin, but if I imagine that defining transitions by the same event foo in multiple parallel states just shouldn’t be allowed. In my eyes the following should throw a spec error:

Control Panel
    foo -> A
    Sorted by Date
      sort by title -> Sorted by Title
    Sorted by Title
      sort by date -> Sorted by Date
    foo -> B
    Zoomed In
      zoom out -> Zoomed Out
    Zoomed Out
     zoom in -> Zoomed In


Thanks for the feedback!

If I’m reading your idea correctly, it looks like you are annotating the parallel children (rather than the parent).


Control Panel

both sort and zoom are active at the same time.
What happens when there’s a third sibling that doesn’t have the prefix?

Control Panel



Yes, by annotating &Sort and &Zoom I indicate that they are a group of sibling states which can be active in parallel.

This group ‘tagged’ by & (let’s say &Group) would behave similar to a ‘regular’ state (like Other), in a way that only one of &Group and Other can be active at a time.

I could also imagine a situation where you have multiple parallel groups like such (using && to indicate a separate parallel group):

Control Panel
  &&Video Playback
  &&Language Selection

This spec would mean that at one moment Control Panel can be in 1 of 3 (mutually exclusive) states:

  • &Group
  • Other
  • &&Group

When in &Group, both &Sort and &Zoom can be active.
When in &&Group, both &&Video Playback and &&Language Selection can be active.

(perhaps a further specification I might like to be able to add is whether &Sort and &Zoom NEED to be both active, but perhaps I’m getting ahead of myself and it can just be written out as the behaviour of this system without it becoming a specified constraint supported by syntax)

Would this break down anywhere?


So the number of ampersands in the prefix implicitly defines a grouping.

Given that the spec already uses indentation for grouping, why not make those groups explicit:

Control Panel
  &Other Group
    Video Playback
    Language Selection

The tradeoff of this is that there’s a bit more typing, of course, but it seems clearer and easier to teach. (Children are indented below parents; only one child of a parent can be active, unless the parent has an ampersand, in which case all of its children are active in parallel)


Update on this topic: we’ve just added in provisional support for parallel states!

To get started:

Thanks for all the feedback on parallel states so far. Give it a dry run and let us know what you think.


This is a great feature, I’m finding this to be an incredibly useful tool and I’m learning a lot by reading the notes and material around it.
One thing I wondered, would it be possible to implement a way of making a transition cause multiple parallel state changes (…something like “Click Menu Button A -> Section_A + Menu_Hide”), or is this inadvisable or better represented in another way?


That’s a great question @mrthomaswhitehead—and something that we wrestled with in developing the parallel states feature.

One perspective is that “transitions should be defined in the states in which their events are possible.” If that’s the case, then you’d probably want to specify transitions to multiple states, as per your example:

    Menu Shown
    Menu Hidden
    Section A
      click menu button -> Menu Hidden, Section B
    Section B
      click menu button -> Menu Hidden, Section A

To us, this felt a little weird on the “to” side of the transition, since we’re trying to convey the configuration of both parallel children. This transition might make more sense on the parallel parent (Example&), but then we lose that information about when the text input event can occur.

The other philosophical approach would be to think of events as completely exogenous—and only focus on how the events affect the states:

    Menu Shown
      click menu button -> Menu Hidden
    Menu Hidden
      click menu button -> Menu Shown
    Section A
      click menu button -> Section B
    Section B
      click menu button -> Section A

This feels rather repetitive, rather than having a single event cause all the necessary actions to occur.

We ultimately decided on the latter to get the feature shipped, but both sides probably have arguments for them. We’re definitely open to thoughts on which approach is best or alternatives.


This is interesting. The more I tried to think of examples of when this feature would be used, the more I found myself describing abstractions of other processes
Shut the door -> Door_Shut, Light_Off
…that could benefit from a pseudo-event describing the causality between the two new states, or attempting to use states to describe and hold variables
Light Fire -> Room_Hot, Room_Light

Does this speak to the value of statecharts being limited to describing smaller components individually, rather than mapping out more complicated systems in single statecharts?


Harel statecharts are capable of modeling complicated systems (he designed them for fighter jets!).

There are a few features that can be helpful which aren’t in @kevin mentioned earlier in the thread that he wasn’t sure how useful parallel states would be without transition guards and extended state variables. The FAQ on the homepage covers a bit on why we haven’t added those.


I’m trying out the feature as it is currently released and I think the way you proposed and implemented it makes total sense for my original use case (

Thanks and congrats on the release :raised_hands: