diff --git a/jstests/concurrency/fsm_workload_helpers/state_transition_utils.js b/jstests/concurrency/fsm_workload_helpers/state_transition_utils.js
new file mode 100644
index 00000000000..2837311f295
--- /dev/null
+++ b/jstests/concurrency/fsm_workload_helpers/state_transition_utils.js
@@ -0,0 +1,29 @@
+
+/*
+ * Genrate uniform distribution transitions matrix for the give states
+ *
+ * All states can be transitioned from all the other state with equal probability.
+ *
+ * e.g.
+ * {
+ * 	state_1: {state_1: 0.5, state_2: 0.5};
+ * 	state_2: {state_1: 0.5, state_2: 0.5};
+ * }
+ */
+
+function uniformDistTransitions(states) {
+    let stateNames = Object.keys(states);
+    let reachableStateNames = stateNames.filter(stateName => stateName != 'init');
+    let prob = 1 / reachableStateNames.length;
+    let transitions = {};
+    reachableStateNames.forEach(stateName => {
+        transitions[stateName] = prob;
+    });
+
+    let allTransitions = {};
+    stateNames.forEach(stateName => {
+        allTransitions[stateName] = transitions;
+    });
+
+    return allTransitions;
+}
diff --git a/jstests/concurrency/fsm_workloads/create_all_type_collections.js b/jstests/concurrency/fsm_workloads/create_all_type_collections.js
new file mode 100644
index 00000000000..9e9692746d1
--- /dev/null
+++ b/jstests/concurrency/fsm_workloads/create_all_type_collections.js
@@ -0,0 +1,214 @@
+'use strict';
+
+/**
+ * Test all kind of collection creation concurrently.
+ *
+ * @tags: [
+ *   requires_sharding,
+ *  ]
+ */
+
+load("jstests/concurrency/fsm_workload_helpers/state_transition_utils.js");
+
+const testDbName = jsTestName() + '_DB';
+const collPrefix = 'coll_';
+const collCount = 10;
+const timeFieldName = "time";
+
+function getRandomCollection(db) {
+    return db.getSiblingDB(testDbName)[collPrefix + Random.randInt(collCount)];
+}
+
+let $config = (function() {
+    let states = {
+        init: function init(db, collName) {},
+
+        createUnsharded: function createUnsharded(db, collName) {
+            let coll = getRandomCollection(db);
+            jsTest.log('Executing state createUnsharded: ' + coll.getFullName());
+            let res = coll.getDB().createCollection(coll.getName());
+
+            assertAlways.commandWorkedOrFailedWithCode(
+                res,
+                [
+                    ErrorCodes.NamespaceExists,
+                    ErrorCodes.StaleConfig,
+                    ErrorCodes.NamespaceNotFound,  // TODO SERVER-60933 remove this error code
+                ],
+                "Failed to create unsharded collection");
+        },
+
+        createView: function createView(db, collName) {
+            let baseColl = getRandomCollection(db);
+            let viewColl = getRandomCollection(db);
+
+            jsTest.log('Executing state createView: viewNss: ' + viewColl.getFullName() +
+                       ' baseColl: ' + baseColl.getFullName());
+
+            let res = baseColl.getDB().createCollection(
+                viewColl.getName(), {viewOn: baseColl.getName(), pipeline: [{'$match': {}}]});
+            assertAlways.commandWorkedOrFailedWithCode(
+                res,
+                [
+                    ErrorCodes.NamespaceExists,
+                    ErrorCodes.StaleConfig,
+                    ErrorCodes.GraphContainsCycle,
+                    ErrorCodes.NamespaceNotFound,  // TODO SERVER-60933 remove this error code
+                ],
+                "Failed to create view");
+        },
+
+        createIndex: function createIndex(db, collName) {
+            let coll = getRandomCollection(db);
+
+            jsTest.log('Executing state createIndex: ' + coll.getFullName());
+
+            let res = coll.createIndex({time: 1});
+
+            assertAlways.commandWorkedOrFailedWithCode(res,
+                                                       [
+                                                           ErrorCodes.CommandNotSupportedOnView,
+                                                           ErrorCodes.NamespaceExists,
+                                                           ErrorCodes.StaleConfig,
+                                                           ErrorCodes.IndexBuildAborted,
+                                                           ErrorCodes.NamespaceNotFound
+                                                       ],
+                                                       "Failed to create index");
+        },
+
+        createTimeseriesUnsharded: function createTimeseriesUnsharded(db, collName) {
+            let coll = getRandomCollection(db);
+            jsTest.log('Executing state createTimeseriesUnsharded: ' + coll.getFullName());
+            let res =
+                coll.getDB().createCollection(coll.getName(), {timeseries: {timeField: 'time'}});
+            assertAlways.commandWorkedOrFailedWithCode(
+                res,
+                [
+                    ErrorCodes.NamespaceExists,
+                    ErrorCodes.StaleConfig,
+                    ErrorCodes.NamespaceNotFound,  // TODO SERVER-60933 remove this error code
+
+                ],
+                "Failed to create unsharded timeseries");
+        },
+
+        drop: function drop(db, collName) {
+            let coll = getRandomCollection(db);
+            const fullNs = coll.getFullName();
+            jsTest.log('Executing state drop: ' + fullNs);
+            assertAlways.eq(true, coll.drop());
+        },
+
+        insert: function insert(db, collName) {
+            let coll = getRandomCollection(db);
+            const fullNs = coll.getFullName();
+            jsTest.log('Executing state insert: ' + fullNs);
+            try {
+                assert.commandWorked(coll.insertOne({time: ISODate()}));
+            } catch (err) {
+                jsTest.log(`failed to insert document ${err}`);
+            }
+        },
+    };
+
+    function teardown(db, collName, cluster) {
+        const shardedCollections = db.getSiblingDB('config')
+                                       .collections.find({'_id': {'$regex': `^${testDbName}\.`}})
+                                       .toArray();
+
+        jsTest.log("Sharded collections: " + tojson(shardedCollections));
+
+        cluster.executeOnMongodNodes((db) => {
+            const localCollections = db.getSiblingDB(testDbName).getCollectionInfos();
+            jsTest.log("Local collections" + tojson(localCollections));
+
+            let encountered = [];
+            localCollections.forEach(coll => {
+                assert(!encountered.includes(coll.name));
+                encountered.push(coll.name);
+
+                /*
+                const shardedCollEntry =
+                    shardedCollections.find(coll => coll._id === `${testDbName}.${coll.name}`);
+                switch (coll.type) {
+                    case 'collection':
+                        if (coll.name.startsWith('system.buckets.')) {
+                            assert(coll.options.hasOwnProperty('timeseries'),
+                                   "Found a bucket collection without timeseries options");
+                            const viewCollName = coll.name.replace(/^system\.buckets\./, '');
+                            let viewColl =
+                                localCollections.find(localColl => localColl.name === viewCollName);
+                            assert(
+                                viewColl,
+                                `Found bucket collection the conresponding view namespace does not exists ${
+                                    coll.name}`);
+                            assert.eq(viewColl.type,
+                                      'timeseries',
+                                      `Timeseries view collection '${
+                                          viewCollName}' is not of type 'timeseries'`);
+                            assert.eq(coll.options.timeseries,
+                                      viewColl.options.timeseries,
+                                      `View and bucket collection for timeseries collection '${
+                                          viewCollName}' have different timeseries options`);
+                            assert(shardedCollEntry === undefined ||
+                                       shardedCollEntry.hasOwnProperty('timeseriesFields'),
+                                   "Found a sharded bucket collection without timeseries options");
+                        } else {
+                            assert(!coll.options.hasOwnProperty('timeseries'),
+                                   "Found a non-bucket collection with timeseries options");
+                            assert(shardedCollEntry === undefined ||
+                                       !shardedCollEntry.hasOwnProperty('timeseriesField'),
+                                   "Found a sharded non-bucket collection with timeseries options");
+                        }
+                        break;
+                    case 'view':
+                        assert(!coll.name.startsWith('system.buckets.'),
+                               "Found a view with a namespace of a bucket collection");
+                        assert(!localCollections.find(localColl => localColl.name ===
+                                                          `system.buckets.${coll.name}`),
+                               `Found a simple view associated to a timeseries bucket collection ${
+                                   coll.name}`);
+                        assert(shardedCollEntry === undefined,
+                               "Found a view registered in the sharding catalog" +
+                                   tojson(shardedCollEntry));
+                        break;
+                    case 'timeseries':
+                        // view namespace for a timesries collection
+                        assert(!coll.name.startsWith('system.buckets.'),
+                               "Found a timeseries view with a namespace of a bucket collection");
+                        assert(coll.options.hasOwnProperty('timeseries'),
+                               `Timeseries view is missing timeseries options`);
+                        let bucketColl = localCollections.find(localColl => localColl.name ===
+                                                                   `system.buckets.${coll.name}`);
+                        assert(
+                            bucketColl,
+                            `Found timeseries view but the conresponding bucket namespace does not exists ${
+                                coll.name}`);
+                        assert.eq(
+                            bucketColl.type,
+                            'collection',
+                            `Bucket collection '${bucketColl.name}' is not of type 'collection'`);
+                        assert.eq(coll.options.timeseries,
+                                  bucketColl.options.timeseries,
+                                  `View and bucket collection for timeseries collection '${
+                                      coll.name}' have different timeseries options`);
+                        assert(shardedCollEntry === undefined,
+                               `Found a timeseries view registered in the sharding catalog ${
+                                   tojson(shardedCollEntry)}`);
+                        break;
+                    default:
+                        doassert("Unrecognized collection type: " + tojsononeline(coll));
+                }
+                */
+            });
+        });
+    }
+
+    return {
+        threadCount: 10,
+        iterations: 50,
+        teardown: teardown,
+        states: states,
+        transitions: uniformDistTransitions(states)
+    };
+})();
