diff --git a/frontend/src/metabase-lib/lib/Question.ts b/frontend/src/metabase-lib/lib/Question.ts
index 61179c141f144214a7796fa6afb6c1afb731f228..e2785b255e9f3b17301ad8f0c79e829d1c542b26 100644
--- a/frontend/src/metabase-lib/lib/Question.ts
+++ b/frontend/src/metabase-lib/lib/Question.ts
@@ -45,7 +45,6 @@ import {
   maybeUsePivotEndpoint,
   MetabaseApi,
 } from "metabase/services";
-import Questions from "metabase/entities/questions";
 import {
   Parameter as ParameterObject,
   ParameterValues,
@@ -1167,39 +1166,6 @@ class QuestionInner {
     }
   }
 
-  // NOTE: prefer `reduxCreate` so the store is automatically updated
-  async apiCreate() {
-    const createdCard = await Questions.api.create(this.card());
-    return this.setCard(createdCard);
-  }
-
-  // NOTE: prefer `reduxUpdate` so the store is automatically updated
-  async apiUpdate() {
-    const updatedCard = await Questions.api.update(this.card());
-    return this.setCard(updatedCard);
-  }
-
-  async reduxCreate(dispatch) {
-    const action = await dispatch(Questions.actions.create(this.card()));
-    return this.setCard(Questions.HACK_getObjectFromAction(action));
-  }
-
-  async reduxUpdate(dispatch, { excludeDatasetQuery = false } = {}) {
-    const fullCard = this.card();
-    const card = excludeDatasetQuery
-      ? _.omit(fullCard, "dataset_query")
-      : fullCard;
-    const action = await dispatch(
-      Questions.actions.update(
-        {
-          id: this.id(),
-        },
-        card,
-      ),
-    );
-    return this.setCard(Questions.HACK_getObjectFromAction(action));
-  }
-
   setParameters(parameters) {
     return this.setCard(assoc(this.card(), "parameters", parameters));
   }
diff --git a/frontend/src/metabase/query_builder/actions/core/core.js b/frontend/src/metabase/query_builder/actions/core/core.js
index dc341de318446d602e866a21165727bfa62f271f..12ca7f3bcbab923217550548bfdb8e3904513645 100644
--- a/frontend/src/metabase/query_builder/actions/core/core.js
+++ b/frontend/src/metabase/query_builder/actions/core/core.js
@@ -1,5 +1,6 @@
 import { createAction } from "redux-actions";
 
+import _ from "underscore";
 import * as MetabaseAnalytics from "metabase/lib/analytics";
 import { loadCard } from "metabase/lib/card";
 import { shouldOpenInBlankWindow } from "metabase/lib/dom";
@@ -181,10 +182,13 @@ export const apiCreateQuestion = question => {
       : question;
 
     const resultsMetadata = getResultsMetadata(getState());
-    const createdQuestion = await questionWithVizSettings
+    const questionToCreate = questionWithVizSettings
       .setQuery(question.query().clean())
-      .setResultsMetadata(resultsMetadata)
-      .reduxCreate(dispatch);
+      .setResultsMetadata(resultsMetadata);
+    const createdQuestion = await reduxCreateQuestion(
+      questionToCreate,
+      dispatch,
+    );
 
     const databases = Databases.selectors.getList(getState());
     if (databases && !databases.some(d => d.is_saved_questions)) {
@@ -226,15 +230,20 @@ export const apiUpdateQuestion = (question, { rerunQuery } = {}) => {
       : question;
 
     const resultsMetadata = getResultsMetadata(getState());
-    const updatedQuestion = await questionWithVizSettings
+    const questionToUpdate = questionWithVizSettings
       .setQuery(question.query().clean())
-      .setResultsMetadata(resultsMetadata)
-      // When viewing a dataset, its dataset_query is swapped with a clean query using the dataset as a source table
-      // (it's necessary for datasets to behave like tables opened in simple mode)
-      // When doing updates like changing name, description, etc., we need to omit the dataset_query in the request body
-      .reduxUpdate(dispatch, {
+      .setResultsMetadata(resultsMetadata);
+
+    // When viewing a dataset, its dataset_query is swapped with a clean query using the dataset as a source table
+    // (it's necessary for datasets to behave like tables opened in simple mode)
+    // When doing updates like changing name, description, etc., we need to omit the dataset_query in the request body
+    const updatedQuestion = await reduxUpdateQuestion(
+      questionToUpdate,
+      dispatch,
+      {
         excludeDatasetQuery: isAdHocModelQuestion(question, originalQuestion),
-      });
+      },
+    );
 
     // reload the question alerts for the current question
     // (some of the old alerts might be removed during update)
@@ -274,3 +283,23 @@ export const revertToRevision = createThunkAction(
     };
   },
 );
+
+async function reduxCreateQuestion(question, dispatch) {
+  const action = await dispatch(Questions.actions.create(question.card()));
+  return question.setCard(Questions.HACK_getObjectFromAction(action));
+}
+
+async function reduxUpdateQuestion(
+  question,
+  dispatch,
+  { excludeDatasetQuery = false },
+) {
+  const fullCard = question.card();
+  const card = excludeDatasetQuery
+    ? _.omit(fullCard, "dataset_query")
+    : fullCard;
+  const action = await dispatch(
+    Questions.actions.update({ id: question.id() }, card),
+  );
+  return question.setCard(Questions.HACK_getObjectFromAction(action));
+}