diff --git a/bddtests/peer_basic.feature b/bddtests/peer_basic.feature
index 7fa29e231582fd8b703d48380d1b2929096aa356..e524a68527f0282ca6c665931db8ce48bc9a1bd6 100644
--- a/bddtests/peer_basic.feature
+++ b/bddtests/peer_basic.feature
@@ -561,9 +561,8 @@ Feature: Network of Peers
             | vp0 | vp1 | vp2 |
 
         # Now start vp3 again
-        Given I start peers:
+        Given I start peers, waiting up to "15" seconds for them to be ready:
             | vp3 |
-        And I wait "15" seconds
 
         # Invoke 10 more txs, this will trigger a state transfer, set a target, and execute new outstanding transactions
         When I invoke chaincode "example2" function name "invoke" on "vp0" "10" times
@@ -614,9 +613,8 @@ Feature: Network of Peers
         Given I stop peers:
             | vp0  |  vp1   | vp2  | vp3  |
 
-        Given I start peers:
+        Given I start peers, waiting up to "15" seconds for them to be ready:
             | vp0  |  vp1   | vp2  | vp3  |
-        And I wait "15" seconds
 
         When I query chaincode "example2" function name "query" with value "a" on peers:
             | vp3  |
@@ -868,9 +866,8 @@ Feature: Network of Peers
             | vp1 | vp2 | vp3 |
 
         # Now start vp1, vp2 again, hopefully retaining pbft state
-        Given I start peers:
+        Given I start peers, waiting up to "15" seconds for them to be ready:
             | vp1 | vp2 |
-        And I wait "15" seconds
 
         # Invoke 1 more tx, if the crash recovery worked, it will commit, otherwise, it will not
         When I invoke chaincode "example2" function name "invoke" on "vp0"
@@ -934,7 +931,7 @@ Feature: Network of Peers
             | vp0  | vp1 | vp2 |
 
         # Now start vp3 again
-        Given I start peers:
+        Given I start peers, waiting up to "15" seconds for them to be ready:
             | vp3  |
 
         # Invoke some more txs, this will trigger a state transfer, but it cannot complete
@@ -1064,9 +1061,8 @@ Feature: Network of Peers
         When requesting "/network/peers" from "vp1"
         Then I should get a JSON response with array "peers" contains "1" elements
 
-        Given I start peers:
+        Given I start peers, waiting up to "15" seconds for them to be ready:
             | vp0  |
-        And I wait "10" seconds
 
         When requesting "/network/peers" from "vp1"
         Then I should get a JSON response with array "peers" contains "2" elements
@@ -1120,10 +1116,9 @@ Scenario: chaincode example02 with 4 peers, stop and start alternates, reverse
     Then I should get a JSON response from peers with "result.message" = "997"
                           | vp0  | vp1 | vp3 |
 
-    Given I start peers:
+    Given I start peers, waiting up to "15" seconds for them to be ready:
                           | vp2  |
 
-    And I wait "15" seconds
     Given I stop peers:
                           | vp1  |
     When I invoke chaincode "example2" function name "invoke" on "vp3" "20" times
@@ -1173,7 +1168,7 @@ Scenario: chaincode example02 with 4 peers, two stopped
         | a  | b  | 10 |
     Then I should have received a transactionID
 
-    Given I start peers:
+    Given I start peers, waiting up to "15" seconds for them to be ready:
         | vp3 |
 
     # Make sure vp3 catches up first
@@ -1197,7 +1192,6 @@ Scenario: chaincode example02 with 4 peers, two stopped
         | vp0 | vp1 | vp3 |
 
 @issue_1874b
-#@doNotDecompose
 Scenario: chaincode example02 with 4 peers, two stopped, bring back vp0
     Given we compose "docker-compose-4-consensus-batch.yml"
     And I register with CA supplying username "binhn" and secret "7avZQLwcUe9q" on peers:
@@ -1243,15 +1237,18 @@ Scenario: chaincode example02 with 4 peers, two stopped, bring back vp0
         | a  | b  | 10 |
     Then I should have received a transactionID
 
-    Given I start peers:
+    Given I start peers, waiting up to "15" seconds for them to be ready:
         | vp0  |
-    And I wait "15" seconds
+
+    # Ensure transaction committed while vp0 was down is part of the ledger
+    Then I wait up to "60" seconds for transaction to be committed to peers:
+        | vp0  | vp1 | vp2 |
 
     When I invoke chaincode "example2" function name "invoke" on "vp1" "8" times
         |arg1|arg2|arg3|
         | a  | b  | 10 |
     Then I should have received a transactionID
-    Then I wait up to "60" seconds for transaction to be committed to peers:
+    Then I wait up to "60" seconds for transactions to be committed to peers:
         | vp0  | vp1 | vp2 |
 
     When I query chaincode "example2" function name "query" with value "a" on peers:
@@ -1294,9 +1291,8 @@ Scenario: chaincode example02 with 4 peers, two stopped, bring back both
         | a  | b  | 10 |
     Then I should have received a transactionID
 
-    Given I start peers:
+    Given I start peers, waiting up to "15" seconds for them to be ready:
         | vp1 | vp2 |
-    And I wait "15" seconds
 
     When I invoke chaincode "example2" function name "invoke" on "vp0" "8" times
         |arg1|arg2|arg3|
diff --git a/bddtests/steps/bdd_compose_util.py b/bddtests/steps/bdd_compose_util.py
index 616caff47fef3119c06d66d82eb59e9f9f2716fe..1c0f516fc4f8c179a42f5ab8537748e11f238020 100644
--- a/bddtests/steps/bdd_compose_util.py
+++ b/bddtests/steps/bdd_compose_util.py
@@ -116,20 +116,22 @@ def getDockerComposeServiceForContainer(containerName):
     return dockerComposeService
 
 def allContainersAreReadyWithinTimeout(context, timeout):
+    allContainers = context.compose_containers
+    return containersAreReadyWithinTimeout(context, allContainers, timeout)
+
+def containersAreReadyWithinTimeout(context, containers, timeout):
     timeoutTimestamp = time.time() + timeout
     formattedTime = time.strftime("%X", time.localtime(timeoutTimestamp))
     bdd_log("All containers should be up by {}".format(formattedTime))
 
-    allContainers = context.compose_containers
-
-    for container in allContainers:
+    for container in containers:
         if not containerIsInitializedByTimestamp(container, timeoutTimestamp):
             return False
 
-    peersAreReady = peersAreReadyByTimestamp(context, allContainers, timeoutTimestamp)
+    peersAreReady = peersAreReadyByTimestamp(context, containers, timeoutTimestamp)
 
     if peersAreReady:
-        bdd_log("All containers in ready state, ready to proceed")
+        bdd_log("Containers in ready state, ready to proceed")
 
     return peersAreReady
 
diff --git a/bddtests/steps/peer_basic_impl.py b/bddtests/steps/peer_basic_impl.py
index 5ead878167a319637f8e8239c9ddd19298ea2ccd..0f660c4b59575da29e48928b55ca491231bf0c89 100644
--- a/bddtests/steps/peer_basic_impl.py
+++ b/bddtests/steps/peer_basic_impl.py
@@ -586,11 +586,14 @@ def step_impl(context):
     assert os.path.isfile(listener), "Please build the block-listener binary!"
     bdd_test_util.start_background_process(context, "eventlistener", [listener, "-listen-to-rejections"] )
 
-
-@given(u'I start peers')
-def step_impl(context):
+@given(u'I start peers, waiting up to "{seconds}" seconds for them to be ready')
+def step_impl(context, seconds):
     compose_op(context, "start")
 
+    timeout = int(seconds)
+    assert bdd_compose_util.allContainersAreReadyWithinTimeout(context, timeout), \
+        "Peers did not come up within {} seconds, aborting.".format(timeout)
+
 @given(u'I stop peers')
 def step_impl(context):
     compose_op(context, "stop")