diff --git a/package-lock.json b/package-lock.json
index 1329236..59372e6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "@flybywiresim/igniter",
-  "version": "1.1.3",
+  "version": "1.1.4",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "@flybywiresim/igniter",
-      "version": "1.1.3",
+      "version": "1.1.4",
       "bin": {
         "igniter": "dist/binary.mjs"
       },
@@ -31,6 +31,7 @@
         "reflect-metadata": "^0.1.13",
         "rollup": "^2.39.0",
         "rollup-plugin-add-shebang": "^0.3.1",
+        "task-pool": "^0.1.1",
         "ts-jest": "^26.5.1",
         "tslib": "^2.1.0",
         "tsyringe": "^4.4.0",
@@ -8994,6 +8995,15 @@
       "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
       "dev": true
     },
+    "node_modules/task-pool": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/task-pool/-/task-pool-0.1.1.tgz",
+      "integrity": "sha1-h3Updv250fthw224DWV37mAY/SE=",
+      "dev": true,
+      "engines": {
+        "node": ">=4.0.0"
+      }
+    },
     "node_modules/terminal-link": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
@@ -16792,6 +16802,12 @@
         }
       }
     },
+    "task-pool": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/task-pool/-/task-pool-0.1.1.tgz",
+      "integrity": "sha1-h3Updv250fthw224DWV37mAY/SE=",
+      "dev": true
+    },
     "terminal-link": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
diff --git a/package.json b/package.json
index cb79211..bcd32ad 100644
--- a/package.json
+++ b/package.json
@@ -35,6 +35,7 @@
     "reflect-metadata": "^0.1.13",
     "rollup": "^2.39.0",
     "rollup-plugin-add-shebang": "^0.3.1",
+    "task-pool": "^0.1.1",
     "ts-jest": "^26.5.1",
     "tslib": "^2.1.0",
     "tsyringe": "^4.4.0",
diff --git a/src/Binary.ts b/src/Binary.ts
index bc53bdd..f3f75bf 100644
--- a/src/Binary.ts
+++ b/src/Binary.ts
@@ -1,4 +1,5 @@
 import { Command } from 'commander';
+import { Pool } from 'task-pool';
 import { findConfigPath, loadConfigTask } from './Helpers';
 import { Context } from './Library/Contracts/Context';
 import { version } from '../package.json';
@@ -7,6 +8,7 @@ import Cache from './Cache';
 
 const binary = (new Command()).version(version)
     .option('-c, --config <filename>', 'set the configuration file name', 'igniter.config.mjs')
+    .option('-j, --num-workers <number>', 'set the maximum number of workers to use', `${Number.MAX_SAFE_INTEGER}`)
     .option('-r, --regex <regex>', 'regular expression used to filter tasks')
     .option('-i, --invert', 'if true, regex will be used to reject tasks')
     .option('--no-cache', 'do not skip tasks, even if hash matches cache')
@@ -24,6 +26,7 @@ const context: Context = {
     dryRun: options.dryRun,
     filterRegex: options.regex ? RegExp(options.regex) : undefined,
     invertRegex: options.invert,
+    taskPool: new Pool({ limit: options.numWorkers }),
 };
 
 // Create and register a cache if needed.
diff --git a/src/Library/Contracts/Context.ts b/src/Library/Contracts/Context.ts
index 24d7c97..c00d9b1 100644
--- a/src/Library/Contracts/Context.ts
+++ b/src/Library/Contracts/Context.ts
@@ -1,3 +1,4 @@
+import { Pool } from 'task-pool';
 import { Cache } from './Cache';
 
 export interface Context {
@@ -7,4 +8,5 @@ export interface Context {
     filterRegex: RegExp|undefined,
     invertRegex: boolean,
     cache?: Cache,
+    taskPool: Pool,
 }
diff --git a/src/Library/Tasks/ExecTask.ts b/src/Library/Tasks/ExecTask.ts
index d3cd6d2..2c7c9a5 100644
--- a/src/Library/Tasks/ExecTask.ts
+++ b/src/Library/Tasks/ExecTask.ts
@@ -1,6 +1,7 @@
 import { exec } from 'child_process';
 import { promisify } from 'util';
 import GenericTask from './GenericTask';
+import { TaskStatus } from '../Contracts/Task';
 
 export default class ExecTask extends GenericTask {
     constructor(
@@ -10,7 +11,18 @@ export default class ExecTask extends GenericTask {
     ) {
         const commands = typeof command === 'string' ? [command] : command;
         super(key, async () => {
-            for await (const cmd of commands) await promisify(exec)(cmd);
+            for await (const cmd of commands) {
+                const poolExec = this.context.taskPool.promise.wrap(promisify(exec));
+
+                const task = poolExec(cmd);
+
+                this.status = TaskStatus.Queued;
+                task.on('run', () => {
+                    this.status = TaskStatus.Running;
+                });
+
+                await task;
+            }
         }, hashFolders);
     }
 }
diff --git a/src/task-pool.d.ts b/src/task-pool.d.ts
new file mode 100644
index 0000000..e7c781f
--- /dev/null
+++ b/src/task-pool.d.ts
@@ -0,0 +1,51 @@
+declare module "task-pool" {
+    export type PoolStyle = 'callback' | 'promise'
+
+    export interface PoolInit {
+        timeout: number,
+        style: PoolStyle,
+        limit: number,
+    }
+
+    export interface PoolTaskOptions {
+        timeout: number,
+        style: PoolStyle,
+    }
+
+    export type PoolTaskFunction<TArgs> = (...args: TArgs[]) => any
+
+    export interface PoolTask<TFnArgs> {
+        fn: PoolTaskFunction<TFnArgs>,
+        timeout: number,
+        style: PoolStyle,
+        args: any[],
+        on: (event: string, fn: (event: any) => void) => void,
+    }
+
+    export type PoolTaskFactory<TPoolStyle extends PoolStyle> = <TArgs>(...args: TArgs[]) =>
+        (TPoolStyle extends 'callback' ?  PoolTask<TArgs> : Promise<any> & PoolTask<any>)
+
+    export class Pool<TPoolStyle extends PoolStyle = 'callback'> {
+        constructor(init: Partial<PoolInit>)
+
+        timeout: Pick<PoolInit, 'timeout'>
+
+        style: TPoolStyle
+
+        limit: Pick<PoolInit, 'limit'>
+
+        running: number
+
+        queue: PoolTask<any>[]
+
+        wrap(Function, options?: Partial<PoolTaskOptions>): PoolTaskFactory<TPoolStyle>
+
+        next()
+
+        start(): boolean
+
+        add(task: PoolTask<any>)
+
+        get promise(): Pool<'promise'>
+    }
+}