diff --git a/docs/includes/apiargs-MongoDBCollection-method-aggregate-option.yaml b/docs/includes/apiargs-MongoDBCollection-method-aggregate-option.yaml
index 1d6e24da687da361f9a792cb94dbe7cbbdeae183..6c7d37bd6fd0ffa9a5f9f673562f3c6db32a10bf 100644
--- a/docs/includes/apiargs-MongoDBCollection-method-aggregate-option.yaml
+++ b/docs/includes/apiargs-MongoDBCollection-method-aggregate-option.yaml
@@ -42,6 +42,18 @@ operation: ~
 optional: true
 ---
 arg_name: option
+name: explain
+type: boolean
+description: |
+  Specifies whether or not to return the information on the processing of the
+  pipeline.
+
+  .. versionadded:: 1.4
+interface: phpmethod
+operation: ~
+optional: true
+---
+arg_name: option
 name: hint
 type: string|array|object
 description: |
diff --git a/src/Operation/Aggregate.php b/src/Operation/Aggregate.php
index ce825144e42e33d2924a0a7f25c9d0cdb2c6e6e9..da1173a05837117257cff7148aa3a7c17aa421ee 100644
--- a/src/Operation/Aggregate.php
+++ b/src/Operation/Aggregate.php
@@ -77,6 +77,9 @@ class Aggregate implements Executable
      *  * comment (string): An arbitrary string to help trace the operation
      *    through the database profiler, currentOp, and logs.
      *
+     *  * explain (boolean): Specifies whether or not to return the information
+     *    on the processing of the pipeline.
+     *
      *  * hint (string|document): The index to use. Specify either the index
      *    name as a string or the index key pattern as a document. If specified,
      *    then the query system will only consider plans using the hinted index.
@@ -160,6 +163,10 @@ class Aggregate implements Executable
             throw InvalidArgumentException::invalidType('"comment" option', $options['comment'], 'string');
         }
 
+        if (isset($options['explain']) && ! is_bool($options['explain'])) {
+            throw InvalidArgumentException::invalidType('"explain" option', $options['explain'], 'boolean');
+        }
+
         if (isset($options['hint']) && ! is_string($options['hint']) && ! is_array($options['hint']) && ! is_object($options['hint'])) {
             throw InvalidArgumentException::invalidType('"hint" option', $options['hint'], 'string or array or object');
         }
@@ -208,6 +215,10 @@ class Aggregate implements Executable
             unset($options['writeConcern']);
         }
 
+        if ( ! empty($options['explain'])) {
+            $options['useCursor'] = false;
+        }
+
         $this->databaseName = (string) $databaseName;
         $this->collectionName = (string) $collectionName;
         $this->pipeline = $pipeline;
@@ -238,16 +249,17 @@ class Aggregate implements Executable
             throw UnsupportedException::writeConcernNotSupported();
         }
 
+        $hasExplain = ! empty($this->options['explain']);
         $hasOutStage = \MongoDB\is_last_pipeline_operator_out($this->pipeline);
 
         $command = $this->createCommand($server);
-        $options = $this->createOptions($hasOutStage);
+        $options = $this->createOptions($hasOutStage, $hasExplain);
 
-        $cursor = $hasOutStage
+        $cursor = ($hasOutStage && ! $hasExplain)
             ? $server->executeReadWriteCommand($this->databaseName, $command, $options)
             : $server->executeReadCommand($this->databaseName, $command, $options);
 
-        if ($this->options['useCursor']) {
+        if ($this->options['useCursor'] || $hasExplain) {
             if (isset($this->options['typeMap'])) {
                 $cursor->setTypeMap($this->options['typeMap']);
             }
@@ -288,7 +300,7 @@ class Aggregate implements Executable
             $cmd['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
         }
 
-        foreach (['comment', 'maxTimeMS'] as $option) {
+        foreach (['comment', 'explain', 'maxTimeMS'] as $option) {
             if (isset($this->options[$option])) {
                 $cmd[$option] = $this->options[$option];
             }
@@ -323,7 +335,7 @@ class Aggregate implements Executable
      * @param boolean $hasOutStage
      * @return array
      */
-    private function createOptions($hasOutStage)
+    private function createOptions($hasOutStage, $hasExplain)
     {
         $options = [];
 
@@ -339,7 +351,7 @@ class Aggregate implements Executable
             $options['session'] = $this->options['session'];
         }
 
-        if ($hasOutStage && isset($this->options['writeConcern'])) {
+        if ($hasOutStage && ! $hasExplain && isset($this->options['writeConcern'])) {
             $options['writeConcern'] = $this->options['writeConcern'];
         }
 
diff --git a/tests/Operation/AggregateFunctionalTest.php b/tests/Operation/AggregateFunctionalTest.php
index 11a43597fc1b23974deadbb9f104e231fdf89af8..95c3ab97dd3a8b9c7ff043602a99306546e0973d 100644
--- a/tests/Operation/AggregateFunctionalTest.php
+++ b/tests/Operation/AggregateFunctionalTest.php
@@ -3,6 +3,7 @@
 namespace MongoDB\Tests\Operation;
 
 use MongoDB\Driver\BulkWrite;
+use MongoDB\Driver\WriteConcern;
 use MongoDB\Operation\Aggregate;
 use MongoDB\Tests\CommandObserver;
 use ArrayIterator;
@@ -131,6 +132,46 @@ class AggregateFunctionalTest extends FunctionalTestCase
         $this->assertEquals($expectedDocuments, iterator_to_array($results));
     }
 
+    public function testExplainOption()
+    {
+        $this->createFixtures(3);
+
+        $pipeline = [['$match' => ['_id' => ['$ne' => 2]]]];
+        $operation = new Aggregate($this->getDatabaseName(), $this->getCollectionName(), $pipeline, ['explain' => true, 'typeMap' => ['root' => 'array']]);
+        $results = iterator_to_array($operation->execute($this->getPrimaryServer()));
+
+        $this->assertCount(1, $results);
+        $this->assertArrayHasKey('stages', $results[0]);
+    }
+
+    public function testExplainOptionWithWriteConcern()
+    {
+        if (version_compare($this->getServerVersion(), '3.4.0', '<')) {
+            $this->markTestSkipped('The writeConcern option is not supported');
+       }
+
+        $this->createFixtures(3);
+
+        $pipeline = [['$match' => ['_id' => ['$ne' => 2]]], ['$out' => $this->getCollectionName() . '.output']];
+        $options = ['explain' => true, 'writeConcern' => new WriteConcern(1)];
+
+        (new CommandObserver)->observe(
+            function() use ($pipeline, $options) {
+                $operation = new Aggregate($this->getDatabaseName(), $this->getCollectionName(), $pipeline, $options);
+
+                $results = iterator_to_array($operation->execute($this->getPrimaryServer()));
+
+                $this->assertCount(1, $results);
+                $this->assertObjectHasAttribute('stages', current($results));
+            },
+            function(stdClass $command) {
+                $this->assertObjectNotHasAttribute('writeConcern', $command);
+            }
+        );
+
+        $this->assertCollectionCount($this->getCollectionName() . '.output', 0);
+    }
+
     public function provideTypeMapOptionsAndExpectedDocuments()
     {
         return [
diff --git a/tests/Operation/AggregateTest.php b/tests/Operation/AggregateTest.php
index d08f8d1dd073cf843bee8dc7322e8544c5e170e0..780411c0b998c3574c678e75554fd1717f3e7336 100644
--- a/tests/Operation/AggregateTest.php
+++ b/tests/Operation/AggregateTest.php
@@ -52,6 +52,10 @@ class AggregateTest extends TestCase
             $options[][] = ['hint' => $value];
         }
 
+        foreach ($this->getInvalidBooleanValues() as $value) {
+            $options[][] = ['explain' => $value];
+        }
+
         foreach ($this->getInvalidIntegerValues() as $value) {
             $options[][] = ['maxAwaitTimeMS' => $value];
         }