CLI tool
machty/ember-concurrency avatar
machty/ember-concurrency

ember-concurrency, tasks that cancel and restart themselves in Ember

ember-concurrency is an Ember Addon that enables you to write concise, worry-free, cancelable, restartable, asynchronous tasks.

688 stars162 forksTypeScriptMIT

At a glance

What is it?
ember-concurrency is an Ember addon for concise, cancelable, restartable asynchronous tasks, and its 4.0 release moved it to the Embroider V2 addon format, which means the consuming app has to configure a Babel transform. That configuration step is the price of admission for the task API, and it is the first thing to check before adopting the library.
Who is it for?
Adopt ember-concurrency if your Ember application has asynchronous work that needs to be cancelled, restarted or polled, since the task primitives and their modifiers cover that pattern directly, and read the Babel transform requirement before you start, because from 4.0 onward the transform is configured in the consuming application and the addon no longer sets it up for you.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 29 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the addon actually gives an Ember application

ember-concurrency describes itself as an Ember addon that lets you write concise, worry-free, cancelable, restartable asynchronous tasks, and the repository calls it improved concurrency primitives for Ember.js. The emphasis is on the lifecycle of asynchronous work rather than on a promise helper.

The distinction matters in an Ember application, where a component can be torn down while a fetch is still in flight, or where a user changes a filter faster than the previous request can return. A task gives that work a name, an owner, and a lifecycle, so it can be cancelled, restarted or dropped when the component goes away. The description of the library as cancelable and restartable is the whole pitch, and the word worry-free in the description is the promise it makes about that lifecycle.

The project is an ember-cli addon, so it is installed the usual way, and it is published to npm under the name ember-concurrency. The badge in the README states Ember 4.0 and above, and there is an Ember Observer badge, which is a compatibility scorecard for addons rather than a marketing claim.

The documentation lives on its own site at ember-concurrency.com, and the README notes something slightly unusual: that site is itself an ember-cli app with interactive examples powered by ember-concurrency, running from the project's test app. So the documentation examples are the library running on itself, which is a decent signal that the documented behaviour is exercised code.

The Babel transform the consuming app must configure

This is the part that trips people up, and the README gives it its own section. ember-concurrency requires a Babel transform that converts tasks written in the async-arrow notation, for example fooTask = task(async () => { /*...*/ }), into generator functions.

The reason for the transform is that the async arrow syntax is not what the task implementation needs under the hood. The library works on generator functions, and the transform bridges the ergonomic syntax people want to write with the form the runtime needs.

Since version 4.0.0 the addon is an Embroider V2 addon, and the README is explicit that the Babel transform now has to be configured on the consuming application or addon rather than inside the library. For a V2 addon, the configuration goes in babel.config.json:

json
{
  "plugins": [
    [
      // ... any other plugins
    "ember-concurrency/async-arrow-task-transform"
  ]
}

For an application, the plugin is added to the babel plugins list in ember-cli-build.js:

js
const app = new EmberApp(defaults, {
  // ...
  babel: {
    plugins: [
      // ... any other plugins
      require.resolve("ember-concurrency/async-arrow-task-transform"),

      // NOTE: put any code coverage plugins last, after the transform.
    ],
  },
});

Two practical notes come out of those snippets. The application form uses require.resolve while the V2 addon form uses the bare package name, because the two build systems resolve plugins differently. And the comment about code coverage plugins is a real ordering constraint: put the transform before coverage plugins, or the instrumented output no longer matches what the transform expects.

Installing it and getting a working build

Installation is the standard ember-cli command, run in your application directory:

bash
    ember install ember-concurrency

After that the plugin has to be added to your Babel configuration, using the snippet above depending on whether you are a consuming application or a V2 addon. The README points at the test application at packages/test-app/ember-cli-build.js as the worked example, which is the fastest way to see the exact shape for your own project.

The repository is a pnpm workspace rather than a single package. The root package.json is private and wires the workspace together with scripts that start the addon and the test app in parallel through concurrently, run the lint tasks per package, and run the test app's test suite. The test script is pnpm --filter test-app run test, and there is a separate test:ember script for the Ember-specific suite.

The toolchain is pinned rather than floated. Volta pins node at 22.14.0 and pnpm at 10.10.0, and the pnpm overrides force ember-cli-htmlbars to ^7.0.1 and @ember/test-waiters to ^4.1.2. There is also a pnpm-workspace.yaml and a pnpm-lock.yaml, so a pnpm install at the root sets up every package in the tree.

One housekeeping script is worth knowing: rm-node-modules uses find with a prune and exec rm -rf to clear every node_modules directory in the tree, which is what you want after a dependency change rather than a manual find and delete.

A pnpm monorepo with separate addon and test app packages

The layout explains how the project is developed. The packages/ directory holds the individual packages, and the scripts refer to the addon package and to a package named test-app, so the test application is a workspace member of the same repository rather than a separate project. The documentation site runs from that test app, which is why the README can claim the interactive examples are powered by the library itself.

There is also a reset script that is worth understanding before you run it. It chains git clean -Xfd and git clean -fd to remove ignored and untracked files, then reinstalls, builds, reinstalls with force and syncs. That is a full reset of the working tree, and it will remove anything you have not committed, so it belongs in a maintenance routine and not in the middle of a feature branch.

The repository also keeps an UPGRADING-2.x.md file next to the CHANGELOG.md, which is a useful signal about the library's history: it has been through a major version change before, and the upgrade notes exist as a separate document from the changelog.

Support has two routes, both named in the README. Bugs and feature requests go to GitHub issues, and the project asks you to try to reproduce the problem inside an ember-twiddle first, which is a faster path to a diagnosis than a large application. Questions go to the e-concurrency channel in the Ember Community Discord server.

The version gap between the package and the published releases

The release list shows 5.2.0 on 2026-02-18, 5.2.1 on 2026-09-19 and 5.3.0 on 2026-09-24, with the last push to master on 2026-09-24. That is a normal pattern: a minor release, a patch, then another minor, with a long quiet stretch in the middle of the year.

The root package.json tells a different story, and the difference is easy to misread. Its version field says 4.0.0-beta.2, but that file is private, it is the workspace root, and its scripts are workspace orchestration rather than a published artifact. The published addon is the one under packages/, and its version is what you get from npm. So the 4.0.0-beta.2 in the root is not a downgrade of the library you install.

The 4.0 boundary still matters for a different reason, and it is the one the README spends a section on. The move to the Embroider V2 addon format happened at 4.0.0, and that is what moved the Babel transform responsibility to the consuming application. If you are reading a blog post from 2021 about ember-concurrency, its install instructions predate the transform requirement entirely.

The licence is MIT, in a LICENSE.md file, so the addon can be used in commercial applications and the code is available to fork if you need to change the task implementation.

Editorial conclusion

Adopt ember-concurrency if your Ember application has asynchronous work that needs to be cancelled, restarted or polled, since the task primitives and their modifiers cover that pattern directly, and read the Babel transform requirement before you start, because from 4.0 onward the transform is configured in the consuming application and the addon no longer sets it up for you. Do not adopt it if you have a single request-response call with no lifecycle, or if you cannot afford the build configuration the V2 format implies. Verify first that the transform plugin ember-concurrency/async-arrow-task-transform is wired into your ember-cli-build.js or babel.config.json, confirm the Ember version your app runs against matches the 4.0 and above badge, and note the release history, where 5.3.0 shipped on 2026-09-24 and the last push was on the same day.

Frequently asked questions

How do I install ember-concurrency in an Ember application?

It is an ember-cli addon, so you run ember install ember-concurrency. Since version 4.0.0 it is an Embroider V2 addon, so you also need to add the ember-concurrency/async-arrow-task-transform Babel plugin in your ember-cli-build.js or babel.config.json.

Why does ember-concurrency need a Babel transform?

The transform converts tasks written in the async-arrow notation, such as fooTask = task(async () => { /*...*/ }), into generator functions, which is the form the library works with. Because 4.0.0 the addon is an Embroider V2 addon, so that transform must be configured on the consuming application or addon.

Which Ember versions does ember-concurrency support?

The badge in the README states Ember 4.0 and above. The repository is a pnpm workspace with a test app alongside the addon, and the published releases include 5.2.0, 5.2.1 and 5.3.0, with 5.3.0 published on 2026-09-24.

How do I develop or run the ember-concurrency test suite?

The root package.json defines the workspace scripts. The test script runs pnpm --filter test-app run test, the start script launches the addon and the test app together with concurrently, and rm-node-modules clears the node_modules directories across the tree after a dependency change.

Where do I get help with ember-concurrency?

The README asks you to open a GitHub issue for problems and feature requests, and to try to reproduce the issue in an ember-twiddle first. Questions can be asked in the e-concurrency channel of the Ember Community Discord server, and the documentation site is ember-concurrency.com.

Official sources

  1. License: MIT
  2. machty/ember-concurrency on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/machty-ember-concurrency.svg)](https://hysenlabs.com/projects/machty-ember-concurrency)

Was this useful?