diff --git a/core/lib/Drupal/Core/Batch/BatchBuilder.php b/core/lib/Drupal/Core/Batch/BatchBuilder.php
new file mode 100644
index 0000000..45b7431
--- /dev/null
+++ b/core/lib/Drupal/Core/Batch/BatchBuilder.php
@@ -0,0 +1,239 @@
+<?php
+
+namespace Drupal\Core\Batch;
+
+/**
+ * Stores a domain object for a batch process.
+ *
+ * Example code to create a batch:
+ * @code
+ * $batch_builder = (new BatchBuilder())
+ *   ->setTitle('Batch Title')
+ *   ->setFinishCallback('batch_example_finished_callback')
+ *   ->setInitMessage('The initialization message (optional)');
+ * foreach ($ids as $id) {
+ *   $batch_builder->addOperation('batch_example_callback', [$id]);
+ * }
+ * batch_set($batch_builder->toArray());
+ * @endcode
+ */
+class BatchBuilder implements BatchBuilderInterface {
+
+  /**
+   * The set of operations to be processed.
+   *
+   * Each operation is a tuple of the function / method to use and an array
+   * containing any parameters to be passed.
+   *
+   * @var array
+   */
+  protected $operations = [];
+
+  /**
+   * The title for the batch.
+   *
+   * @var string
+   */
+  protected $title = 'Processing';
+
+  /**
+   * The initializing message for the batch.
+   *
+   * @var string
+   */
+  protected $initMessage = 'Initializing.';
+
+  /**
+   * The message to be shown while the batch is in progress.
+   *
+   * @var string
+   */
+  protected $progressMessage = 'Completed @current of @total.';
+
+  /**
+   * The message to be shown if a problem occurs.
+   *
+   * @var string
+   */
+  protected $errorMessage = 'An error has occurred.';
+
+  /**
+   * The name of a function / method to be called when the batch finishes.
+   *
+   * @var string
+   */
+  protected $finished;
+
+  /**
+   * The file containing the operation and finished callbacks.
+   *
+   * If the callbacks are in the .module file or are static methods of a class,
+   * then this does not need to be set.
+   *
+   * @var string
+   */
+  protected $file;
+
+  /**
+   * An array of libraries to be included when processing the batch.
+   *
+   * @var string[]
+   */
+  protected $libraries = [];
+
+  /**
+   * An array of options to be used with the redirect URL.
+   *
+   * @var array
+   */
+  protected $urlOptions = [];
+
+  /**
+   * Specifies if the batch is progressive.
+   *
+   * If true, multiple calls are used. Otherwise an attempt is made to process
+   * the batch in on page call.
+   *
+   * @var bool
+   */
+  protected $progressive = TRUE;
+
+  /**
+   * The details of the queue to use.
+   *
+   * A tuple containing the name of the queue and the class of the queue to use.
+   *
+   * @var array
+   */
+  protected $queue;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setTitle($title) {
+    $this->title = $title;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setFinishCallback(callable $callback) {
+    $this->finished = $callback;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setInitMessage($message) {
+    $this->initMessage = $message;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setProgressMessage($message) {
+    $this->progressMessage = $message;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setErrorMessage($message) {
+    $this->errorMessage = $message;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setFile($filename) {
+    $this->file = $filename;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setLibraries(array $libraries) {
+    $this->libraries = $libraries;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUrlOptions(array $options = []) {
+    $this->urlOptions = $options;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setProgressive($is_progressive = TRUE) {
+    $this->progressive = $is_progressive;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setQueue($name, $class) {
+    if (!class_exists($class)) {
+      throw new \InvalidArgumentException('Class ' . $class . ' does not exist.');
+    }
+
+    $this->queue = [
+      'name' => $name,
+      'class' => $class,
+    ];
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addOperation(callable $callback, array $arguments = []) {
+    $this->operations[] = [$callback, $arguments];
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function addLibraries($libraries) {
+    $this->libraries = array_unique(
+      array_merge($this->libraries, (array) $libraries)
+    );
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function toArray() {
+    $array = [
+      'operations' => $this->operations ?: [],
+      'title' => $this->title ?: '',
+      'init_message' => $this->initMessage ?: '',
+      'progress_message' => $this->progressMessage ?: '',
+      'error_message' => $this->errorMessage ?: '',
+      'finished' => $this->finished,
+      'file' => $this->file,
+      'library' => $this->libraries ?: [],
+      'url_options' => $this->urlOptions ?: [],
+      'progressive' => $this->progressive,
+    ];
+
+    if ($this->queue) {
+      $array['queue'] = $this->queue;
+    }
+
+    return $array;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Batch/BatchBuilderInterface.php b/core/lib/Drupal/Core/Batch/BatchBuilderInterface.php
new file mode 100644
index 0000000..8a5b1ea
--- /dev/null
+++ b/core/lib/Drupal/Core/Batch/BatchBuilderInterface.php
@@ -0,0 +1,160 @@
+<?php
+
+namespace Drupal\Core\Batch;
+
+/**
+ * Defines an interface for batch builder classes.
+ */
+interface BatchBuilderInterface {
+
+  /**
+   * Sets the title.
+   *
+   * @param string $title
+   *   The title.
+   *
+   * @return $this
+   */
+  public function setTitle($title);
+
+  /**
+   * Sets the finished callback.
+   *
+   * This callback will be executed if the batch process is done.
+   *
+   * @param callable $callback
+   *   The callback.
+   *
+   * @return $this
+   */
+  public function setFinishCallback(callable $callback);
+
+  /**
+   * Sets the displayed message while processing is initialized.
+   *
+   * @param string $message
+   *   The text to display. Defaults to 'Initializing.'.
+   *
+   * @return $this
+   */
+  public function setInitMessage($message);
+
+  /**
+   * Sets the message to display when the batch is being processed.
+   *
+   * @param string $message
+   *   The text to display.  Available placeholders are '@current',
+   *   '@remaining', '@total', '@percentage', '@estimate' and '@elapsed'.
+   *   Defaults to 'Completed @current of @total.'.
+   *
+   * @return $this
+   */
+  public function setProgressMessage($message);
+
+  /**
+   * Sets the message to display if an error occurs while processing.
+   *
+   * @param string $message
+   *   The text to display. Defaults to 'An error has occurred.'.
+   *
+   * @return $this
+   */
+  public function setErrorMessage($message);
+
+  /**
+   * Sets the file that contains the callback functions.
+   *
+   * The path should be relative to base_path(), and thus should be built using
+   * drupal_get_path(). Defaults to {module_name}.module.
+   *
+   * @param string $filename
+   *   The path to the file.
+   *
+   * @return $this
+   */
+  public function setFile($filename);
+
+  /**
+   * Sets the libraries to use when processing the batch.
+   *
+   * Adds the libraries for use on the progress page. Any previously added
+   * libraries are removed. Use \Drupal\Core\Batch\Batch::addLibraries() to add
+   * one or more libraries.
+   *
+   * @param string[] $libraries
+   *   The libraries to be used.
+   *
+   * @return $this
+   */
+  public function setLibraries(array $libraries);
+
+  /**
+   * Sets the options for redirect URLs.
+   *
+   * @param array $options
+   *   The options to use.
+   *
+   * @return $this
+   *
+   * @see \Drupal\Core\Url
+   */
+  public function setUrlOptions(array $options = []);
+
+  /**
+   * Sets the batch to run progressively.
+   *
+   * @param bool $is_progressive
+   *   TRUE (default) indicates that the batch will run in more than one run.
+   *   FALSE indicates that the batch will finish in a single run.
+   *
+   * @return $this
+   */
+  public function setProgressive($is_progressive = TRUE);
+
+  /**
+   * Sets or removes an override for the default queue.
+   *
+   * @param string $name
+   *   The unique identifier for the queue.
+   * @param string $class
+   *   The fully qualified name of a class that implements
+   *   \Drupal\Core\Queue\QueueInterface. Typically, the class will either
+   *   be \Drupal\Core\Queue\Batch or \Drupal\Core\Queue\BatchMemory. Defaults
+   *   to Batch if progressive is TRUE, or to BatchMemory if progressive is
+   *   FALSE.
+   *
+   * @return $this
+   */
+  public function setQueue($name, $class);
+
+  /**
+   * Adds a batch operation.
+   *
+   * @param callable $callback
+   *   The name of the callback function.
+   * @param array $arguments
+   *   An array of arguments to pass to the callback function.
+   *
+   * @return $this
+   */
+  public function addOperation(callable $callback, array $arguments = []);
+
+  /**
+   * Adds libraries to be used on the process page.
+   *
+   * @param string|string[] $libraries
+   *   The libraries to add.
+   *
+   * @return $this
+   */
+  public function addLibraries($libraries);
+
+  /**
+   * Converts a \Drupal\Core\Batch\Batch object into an array.
+   *
+   * @return array
+   *   The array representation of the object.
+   */
+  public function toArray();
+
+}
diff --git a/core/modules/system/tests/src/Unit/Batch/BatchBuilderTest.php b/core/modules/system/tests/src/Unit/Batch/BatchBuilderTest.php
new file mode 100644
index 0000000..0a6816a
--- /dev/null
+++ b/core/modules/system/tests/src/Unit/Batch/BatchBuilderTest.php
@@ -0,0 +1,246 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\system\Unit\Batch\BatchBuilderTest.
+ */
+
+namespace Drupal\Tests\system\Unit\Batch;
+
+use Drupal\Core\Batch\BatchBuilder;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Tests for the batch builder class.
+ *
+ * @coversDefaultClass \Drupal\Core\Batch\BatchBuilder
+ *
+ * @group system
+ */
+class BatchBuilderTest extends UnitTestCase {
+
+  /**
+   * Tests the default values.
+   *
+   * @covers ::toArray
+   */
+  public function testSensibleDefaultValues() {
+    $batch = (new BatchBuilder())->toArray();
+
+    $this->assertTrue(is_array($batch), 'Batch builder create an array.');
+    $this->assertTrue(is_array($batch['operations']), 'Operations array exists.');
+    $this->assertEmpty($batch['operations'], 'Operations array is empty.');
+    $this->assertEquals('Processing', $batch['title'], 'Default title has been set.');
+    $this->assertEquals('Initializing.', $batch['init_message'], 'Default initialization message has been set.');
+    $this->assertEquals('Completed @current of @total.', $batch['progress_message'], 'Default progess message has been set.');
+    $this->assertEquals('An error has occurred.', $batch['error_message'], 'Default error message has been set.');
+    $this->assertNull($batch['finished'], 'Finished callback has not been set.');
+    $this->assertNull($batch['file'], 'No file is to be included.');
+    $this->assertTrue(is_array($batch['library']), 'Library array exists.');
+    $this->assertEmpty($batch['library'], 'No libraries have been added.');
+    $this->assertTrue(is_array($batch['url_options']), 'URL options array exists.');
+    $this->assertEmpty($batch['url_options'], 'URL options array is empty.');
+    $this->assertTrue($batch['progressive'], 'Progressive has been set.');
+    $this->assertFalse(isset($batch['queue']), 'Queue has not been set.');
+  }
+
+  /**
+   * Tests setTitle().
+   *
+   * @covers ::setTitle
+   */
+  public function testSetTitle() {
+    $batch = (new BatchBuilder())
+      ->setTitle('New Title')
+      ->toArray();
+
+    $this->assertEquals('New Title', $batch['title'], 'Title has been set.');
+  }
+
+  /**
+   * Tests setFinishCallback().
+   *
+   * @covers ::setFinishCallback
+   */
+  public function testSetFinishCallback() {
+    $batch = (new BatchBuilder())
+      ->setFinishCallback('\Drupal\Tests\system\Unit\Batch\BatchBuilderTest::finishedCallback')
+      ->toArray();
+
+    $this->assertEquals('\Drupal\Tests\system\Unit\Batch\BatchBuilderTest::finishedCallback', $batch['finished'], 'Finish callback has been set');
+  }
+
+  /**
+   * Tests setInitMessage().
+   *
+   * @covers ::setInitMessage
+   */
+  public function testSetInitMessage() {
+    $batch = (new BatchBuilder())
+      ->setInitMessage('New initialization message.')
+      ->toArray();
+
+    $this->assertEquals('New initialization message.', $batch['init_message'], 'Initialization message has been set/');
+  }
+
+  /**
+   * Tests setProgressMessage().
+   *
+   * @covers ::setProgressMessage
+   */
+  public function testSetProgressMessage() {
+    $batch = (new BatchBuilder())
+      ->setProgressMessage('Batch in progress...')
+      ->toArray();
+
+    $this->assertEquals('Batch in progress...', $batch['progress_message'], 'Progress message has been set.');
+  }
+
+  /**
+   * Tests setErrorMessage().
+   */
+  public function testSetErrorMessage() {
+    $batch = (new BatchBuilder())
+      ->setErrorMessage('Ooops. An error has occurred :(')
+      ->toArray();
+
+    $this->assertEquals('Ooops. An error has occurred :(', $batch['error_message'], 'Error message has been set.');
+  }
+
+  /**
+   * Tests setFile().
+   *
+   * @covers ::setFile
+   */
+  public function testSetFile() {
+    $batch = (new BatchBuilder())
+      ->setFile('filename.php')
+      ->toArray();
+
+    $this->assertEquals('filename.php', $batch['file'], 'The file has been set.');
+  }
+
+  /**
+   * Tests setting and adding libraries.
+   *
+   * @covers ::setLibraries
+   * @covers ::addLibraries
+   */
+  public function testAddingLibraries() {
+    $batch_builder = new BatchBuilder();
+    $batch = $batch_builder
+      ->addLibraries('library1')
+      ->toArray();
+
+    $this->assertEquals(1, count($batch['library']), 'Library added as string.');
+
+    $batch = $batch_builder
+      ->addLibraries(['library2', 'library3'])
+      ->toArray();
+
+    $this->assertEquals(3, count($batch['library']), 'Libraries added in an array.');
+
+    $batch = $batch_builder
+      ->setLibraries(['onlylibrary'])
+      ->toArray();
+
+    $this->assertEquals(1, count($batch['library']), 'Libraries replaced by an array.');
+  }
+
+  /**
+   * Tests setProgressive().
+   *
+   * @covers ::setProgressive
+   */
+  public function testSetProgressive() {
+    $batch_builder = new BatchBuilder();
+    $batch = $batch_builder
+      ->setProgressive(FALSE)
+      ->toArray();
+
+    $this->assertFalse($batch['progressive'], 'Batch has been set to not progressive.');
+
+    $batch = $batch_builder
+      ->setProgressive(TRUE)
+      ->toArray();
+
+    $this->assertTrue($batch['progressive'], 'Batch has been set to progressive.');
+  }
+
+  /**
+   * Tests setQueue().
+   *
+   * @covers ::setQueue
+   */
+  public function testSetQueue() {
+    $batch = (new BatchBuilder())
+      ->setQueue('BatchName', '\Drupal\Core\Queue\Batch')
+      ->toArray();
+
+    $this->assertArrayEquals([
+      'name' => 'BatchName',
+      'class' => '\Drupal\Core\Queue\Batch',
+    ], $batch['queue'], 'Batch queue has been set.');
+  }
+
+  /**
+   * Tests setUrlOptions().
+   *
+   * @covers ::setUrlOptions
+   */
+  public function testSetUrlOptions() {
+    $options = [
+      'absolute' => TRUE,
+      'language' => 'de',
+    ];
+    $batch = (new BatchBuilder())
+      ->setUrlOptions($options)
+      ->toArray();
+
+    $this->assertEquals($options, $batch['url_options'], 'URL options have been set.');
+  }
+
+  /**
+   * Tests addOperation().
+   *
+   * @covers ::addOperation
+   */
+  public function testAddOperation() {
+    $batch_builder = new BatchBuilder();
+    $batch = $batch_builder
+      ->addOperation('\Drupal\Tests\system\Unit\Batch\BatchBuilderTest::operationCallback')
+      ->toArray();
+
+    $this->assertEquals(1, count($batch['operations']), 'One operation has been added.');
+
+    $batch = $batch_builder
+      ->addOperation('\Drupal\Tests\system\Unit\Batch\BatchBuilderTest::operationCallback', [2])
+      ->addOperation('\Drupal\Tests\system\Unit\Batch\BatchBuilderTest::operationCallback', [3])
+      ->toArray();
+
+    $this->assertEquals(3, count($batch['operations']), 'Three operations have been added.');
+
+    $this->assertEquals('\Drupal\Tests\system\Unit\Batch\BatchBuilderTest::operationCallback', $batch['operations'][0][0], 'Operation callback has been set.');
+    $this->assertEquals([], $batch['operations'][0][1], 'First operation parameters set correctly.');
+    $this->assertEquals([2], $batch['operations'][1][1], 'Second operation parameters set correctly.');
+    $this->assertEquals([3], $batch['operations'][2][1], 'Third operation parameters set correctly.');
+
+  }
+
+  /**
+   * Empty callback for the tests.
+   *
+   * @internal
+   */
+  public static function finishedCallback() {
+  }
+
+  /**
+   * Empty callback for the tests.
+   *
+   * @internal
+   */
+  public static function operationCallback() {
+  }
+
+}
