diff --git a/platform/features/layout/src/LayoutController.js b/platform/features/layout/src/LayoutController.js
index b30de80ba3..017793d2e6 100644
--- a/platform/features/layout/src/LayoutController.js
+++ b/platform/features/layout/src/LayoutController.js
@@ -45,7 +45,8 @@ define(
          * @param {Scope} $scope the controller's Angular scope
          */
         function LayoutController($scope) {
-            var self = this;
+            var self = this,
+                callbackCount = 0;
 
             // Update grid size when it changed
             function updateGridSize(layoutGrid) {
@@ -91,23 +92,26 @@ define(
                 e.preventDefault();
             }
 
-            function getComposition(domainObject){
-                return domainObject.useCapability('composition');
-            }
-
-            function composeView (composition){
-                $scope.composition = composition;
-                return composition.map(function (object) {
-                        return object.getId();
-                    }) || [];
-            }
-
             //Will fetch fully contextualized composed objects, and populate
             // scope with them.
-            function refreshComposition(ids) {
-                return getComposition($scope.domainObject)
-                    .then(composeView)
-                    .then(function(ids){self.layoutPanels(ids);});
+            function refreshComposition() {
+                //Keep a track of how many composition callbacks have been made
+                var thisCount = ++callbackCount;
+
+                $scope.domainObject.useCapability('composition').then(function(composition){
+                    var ids;
+
+                    //Is this callback for the most recent composition
+                    // request? If not, discard it. Prevents race condition
+                    if (thisCount === callbackCount){
+                        ids = composition.map(function (object) {
+                                return object.getId();
+                            }) || [];
+
+                        $scope.composition = composition;
+                        self.layoutPanels(ids);
+                    }
+                });
             }
 
             // End drag; we don't want to put $scope into this
diff --git a/platform/features/layout/test/LayoutControllerSpec.js b/platform/features/layout/test/LayoutControllerSpec.js
index dcafefc718..bbed271d2c 100644
--- a/platform/features/layout/test/LayoutControllerSpec.js
+++ b/platform/features/layout/test/LayoutControllerSpec.js
@@ -33,7 +33,8 @@ define(
                 testConfiguration,
                 controller,
                 mockCompositionCapability,
-                mockComposition;
+                mockComposition,
+                mockCompositionObjects;
 
             function mockPromise(value){
                 return {
@@ -67,6 +68,7 @@ define(
                 testModel = {};
 
                 mockComposition = ["a", "b", "c"];
+                mockCompositionObjects = mockComposition.map(mockDomainObject);
 
                 testConfiguration = {
                     panels: {
@@ -77,7 +79,7 @@ define(
                     }
                 };
 
-                mockCompositionCapability = mockPromise(mockComposition.map(mockDomainObject));
+                mockCompositionCapability = mockPromise(mockCompositionObjects);
 
                 mockScope.domainObject = mockDomainObject("mockDomainObject");
                 mockScope.model = testModel;
@@ -107,6 +109,30 @@ define(
                 );
             });
 
+            it("Is robust to concurrent changes to composition", function () {
+                var secondMockComposition = ["a", "b", "c", "d"],
+                    secondMockCompositionObjects = secondMockComposition.map(mockDomainObject),
+                    firstCompositionCB,
+                    secondCompositionCB;
+
+                spyOn(mockCompositionCapability, "then");
+                mockScope.$watchCollection.mostRecentCall.args[1]();
+                mockScope.$watchCollection.mostRecentCall.args[1]();
+
+                firstCompositionCB = mockCompositionCapability.then.calls[0].args[0];
+                secondCompositionCB = mockCompositionCapability.then.calls[1].args[0];
+
+                //Resolve promises in reverse order
+                secondCompositionCB(secondMockCompositionObjects);
+                firstCompositionCB(mockCompositionObjects);
+
+                //Expect the promise call that was initiated most recently to
+                // be the one used to populate scope, irrespective of order that
+                // it was eventually resolved
+                expect(mockScope.composition).toBe(secondMockCompositionObjects);
+            });
+
+
             it("provides styles for frames, from configuration", function () {
                 mockScope.$watchCollection.mostRecentCall.args[1]();
                 expect(controller.getFrameStyle("a")).toEqual({