diff --git a/e2e/support/helpers/e2e-qa-databases-helpers.js b/e2e/support/helpers/e2e-qa-databases-helpers.js
index 2f96be93fe0e49376ca5fccc4f7ed2e24422af6a..c77b405273e83dad1470e15b7df727322e0ad53b 100644
--- a/e2e/support/helpers/e2e-qa-databases-helpers.js
+++ b/e2e/support/helpers/e2e-qa-databases-helpers.js
@@ -185,6 +185,29 @@ export function getTableId({ databaseId = WRITABLE_DB_ID, name }) {
     });
 }
 
+export const createModelFromTableName = ({
+  tableName,
+  modelName = "Test Action Model",
+  idAlias = 'modelId'
+}) => {
+  getTableId({ name: tableName }).then(tableId => {
+    cy.createQuestion(
+      {
+        database: WRITABLE_DB_ID,
+        name: modelName,
+        query: {
+          "source-table": tableId,
+        },
+        dataset: true,
+      },
+      {
+        wrapId: true,
+        idAlias,
+      },
+    );
+  });
+};
+
 export function waitForSyncToFinish({ iteration = 0, dbId = 2, tableName = '' }) {
   // 100 x 100ms should be plenty of time for the sync to finish.
   if (iteration === 100) {
diff --git a/e2e/test/scenarios/dashboard/actions-on-dashboards.cy.spec.js b/e2e/test/scenarios/dashboard/actions-on-dashboards.cy.spec.js
index 11e97d18e6fd6ac6b8a50528b790adc51bec338a..843ac1ce54666661b2c039d6da9938a35990cee2 100644
--- a/e2e/test/scenarios/dashboard/actions-on-dashboards.cy.spec.js
+++ b/e2e/test/scenarios/dashboard/actions-on-dashboards.cy.spec.js
@@ -2,7 +2,7 @@ import {
   restore,
   queryWritableDB,
   resetTestTable,
-  getTableId,
+  createModelFromTableName,
   fillActionQuery,
   resyncDatabase,
   visitDashboard,
@@ -55,6 +55,7 @@ const MODEL_NAME = "Test Action Model";
           restore(`${dialect}-writable`);
           cy.signInAsAdmin();
           resyncDatabase({ dbId: WRITABLE_DB_ID, tableName: TEST_TABLE });
+          createModelFromTableName({ tableName: TEST_TABLE, modelName: MODEL_NAME });
         });
 
         it("adds a custom query action to a dashboard and runs it", () => {
@@ -68,8 +69,6 @@ const MODEL_NAME = "Test Action Model";
             expect(result.rows[0].score).to.equal(0);
           });
 
-          createModelFromTable(TEST_TABLE);
-
           cy.get("@modelId").then(id => {
             cy.visit(`/model/${id}/detail`);
             cy.wait(["@getModel", "@getModelActions", "@getCardAssociations"]);
@@ -124,7 +123,6 @@ const MODEL_NAME = "Test Action Model";
         });
 
         it("adds an implicit create action to a dashboard and runs it", () => {
-          createModelFromTable(TEST_TABLE);
           cy.get("@modelId").then(id => {
             createImplicitAction({
               kind: "create",
@@ -160,8 +158,6 @@ const MODEL_NAME = "Test Action Model";
         it("adds an implicit update action to a dashboard and runs it", () => {
           const actionName = "Update";
 
-          createModelFromTable(TEST_TABLE);
-
           cy.get("@modelId").then(id => {
             createImplicitAction({
               kind: "update",
@@ -216,8 +212,6 @@ const MODEL_NAME = "Test Action Model";
             expect(result.rows[0].id).to.equal(3);
           });
 
-          createModelFromTable(TEST_TABLE);
-
           cy.get("@modelId").then(id => {
             createImplicitAction({
               kind: "delete",
@@ -252,11 +246,11 @@ const MODEL_NAME = "Test Action Model";
           resetTestTable({ type: dialect, table: TEST_COLUMNS_TABLE });
           restore(`${dialect}-writable`);
           cy.signInAsAdmin();
-          resyncDatabase({ dbId: WRITABLE_DB_ID, tableName: TEST_TABLE });
+          resyncDatabase({ dbId: WRITABLE_DB_ID, tableName: TEST_COLUMNS_TABLE });
+          createModelFromTableName({ tableName: TEST_COLUMNS_TABLE, modelName: MODEL_NAME });
         });
 
         it("can update various data types via implicit actions", () => {
-          createModelFromTable(TEST_COLUMNS_TABLE);
           cy.get("@modelId").then(id => {
             createImplicitAction({
               kind: "update",
@@ -353,7 +347,6 @@ const MODEL_NAME = "Test Action Model";
         });
 
         it("can insert various data types via implicit actions", () => {
-          createModelFromTable(TEST_COLUMNS_TABLE);
           cy.get("@modelId").then(id => {
             createImplicitAction({
               kind: "create",
@@ -439,7 +432,6 @@ const MODEL_NAME = "Test Action Model";
         });
 
         it("does not show json, enum, or binary columns for implicit actions", () => {
-          createModelFromTable(TEST_COLUMNS_TABLE);
           cy.get("@modelId").then(id => {
             createImplicitAction({
               kind: "create",
@@ -468,7 +460,6 @@ const MODEL_NAME = "Test Action Model";
         });
 
         it("properly loads and updates date and time fields for implicit update actions", () => {
-          createModelFromTable(TEST_COLUMNS_TABLE);
           cy.get("@modelId").then(id => {
             createImplicitAction({
               kind: "update",
@@ -581,25 +572,6 @@ const MODEL_NAME = "Test Action Model";
     });
 });
 
-const createModelFromTable = tableName => {
-  getTableId({ name: tableName }).then(tableId => {
-    cy.createQuestion(
-      {
-        database: WRITABLE_DB_ID,
-        name: MODEL_NAME,
-        query: {
-          "source-table": tableId,
-        },
-        dataset: true,
-      },
-      {
-        wrapId: true,
-        idAlias: "modelId",
-      },
-    );
-  });
-};
-
 function createDashboardWithActionButton({
   actionName,
   modelName = MODEL_NAME,
diff --git a/e2e/test/scenarios/models/model-actions.cy.spec.js b/e2e/test/scenarios/models/model-actions.cy.spec.js
index 07868197f5ba6cc4115c45b3de992bcd5dc5e23d..f1911d575bfa4ae20c05699bca21d39c32f08740 100644
--- a/e2e/test/scenarios/models/model-actions.cy.spec.js
+++ b/e2e/test/scenarios/models/model-actions.cy.spec.js
@@ -1,3 +1,4 @@
+import { assocIn } from "icepick";
 import {
   setActionsEnabledForDB,
   modal,
@@ -7,13 +8,19 @@ import {
   createAction,
   navigationSidebar,
   openNavigationSidebar,
+  resetTestTable,
+  resyncDatabase,
+  createModelFromTableName,
+  queryWritableDB,
 } from "e2e/support/helpers";
-import { SAMPLE_DB_ID, USER_GROUPS } from "e2e/support/cypress_data";
+
+import { SAMPLE_DB_ID, USER_GROUPS, WRITABLE_DB_ID } from "e2e/support/cypress_data";
 
 import { createMockActionParameter } from "metabase-types/api/mocks";
 
 const PG_DB_ID = 2;
 const PG_ORDERS_TABLE_ID = 9;
+const WRITABLE_TEST_TABLE = "scoreboard_actions";
 
 const SAMPLE_ORDERS_MODEL = {
   name: "Order",
@@ -68,6 +75,12 @@ const SAMPLE_QUERY_ACTION = {
   },
 };
 
+const SAMPLE_WRITABLE_QUERY_ACTION = assocIn(
+  SAMPLE_QUERY_ACTION,
+  ["dataset_query", "native", "query"],
+  `UPDATE ${WRITABLE_TEST_TABLE} SET score = 22 WHERE id = {{ ${TEST_TEMPLATE_TAG.name} }}`,
+);
+
 describe(
   "scenarios > models > actions",
   { tags: ["@external", "@actions"] },
@@ -193,105 +206,6 @@ describe(
       cy.findByText(QUERY).should("be.visible");
     });
 
-    it("should allow to execute actions from the model page", () => {
-      cy.get("@modelId").then(modelId => {
-        createAction({
-          ...SAMPLE_QUERY_ACTION,
-          model_id: modelId,
-        });
-        cy.visit(`/model/${modelId}/detail/actions`);
-        cy.wait("@getModel");
-      });
-
-      runActionFor(SAMPLE_QUERY_ACTION.name);
-
-      modal().within(() => {
-        cy.findByLabelText(TEST_PARAMETER.name).type("1");
-        cy.button(SAMPLE_QUERY_ACTION.name).click();
-      });
-
-      cy.findByText(`${SAMPLE_QUERY_ACTION.name} ran successfully`).should(
-        "be.visible",
-      );
-    });
-
-    it("should allow to make actions public and execute them", () => {
-      const IMPLICIT_ACTION_NAME = "Update order";
-
-      cy.get("@modelId").then(modelId => {
-        createAction({
-          ...SAMPLE_QUERY_ACTION,
-          model_id: modelId,
-        });
-        createAction({
-          type: "implicit",
-          kind: "row/update",
-          name: IMPLICIT_ACTION_NAME,
-          model_id: modelId,
-        });
-        cy.visit(`/model/${modelId}/detail/actions`);
-        cy.wait("@getModel");
-      });
-
-      enableSharingFor(SAMPLE_QUERY_ACTION.name, {
-        publicUrlAlias: "queryActionPublicUrl",
-      });
-      enableSharingFor(IMPLICIT_ACTION_NAME, {
-        publicUrlAlias: "implicitActionPublicUrl",
-      });
-
-      cy.signOut();
-
-      cy.get("@queryActionPublicUrl").then(url => {
-        cy.visit(url);
-        cy.findByLabelText(TEST_PARAMETER.name).type("1");
-        cy.button(SAMPLE_QUERY_ACTION.name).click();
-        cy.findByText(`${SAMPLE_QUERY_ACTION.name} ran successfully`).should(
-          "be.visible",
-        );
-        cy.findByRole("form").should("not.exist");
-        cy.button(SAMPLE_QUERY_ACTION.name).should("not.exist");
-      });
-
-      cy.get("@implicitActionPublicUrl").then(url => {
-        cy.visit(url);
-
-        // Order 1 has quantity 2 by default, so we're not actually mutating data
-        cy.findByLabelText("Id").type("1");
-        cy.findByLabelText(/quantity/i).type("2");
-
-        cy.button(IMPLICIT_ACTION_NAME).click();
-        cy.findByText(`${IMPLICIT_ACTION_NAME} ran successfully`).should(
-          "be.visible",
-        );
-        cy.findByRole("form").should("not.exist");
-        cy.button(IMPLICIT_ACTION_NAME).should("not.exist");
-      });
-
-      cy.signInAsAdmin();
-      cy.get("@modelId").then(modelId => {
-        cy.visit(`/model/${modelId}/detail/actions`);
-        cy.wait("@getModel");
-      });
-
-      disableSharingFor(SAMPLE_QUERY_ACTION.name);
-      disableSharingFor(IMPLICIT_ACTION_NAME);
-
-      cy.get("@queryActionPublicUrl").then(url => {
-        cy.visit(url);
-        cy.findByRole("form").should("not.exist");
-        cy.button(SAMPLE_QUERY_ACTION.name).should("not.exist");
-        cy.findByText("Not found").should("be.visible");
-      });
-
-      cy.get("@implicitActionPublicUrl").then(url => {
-        cy.visit(url);
-        cy.findByRole("form").should("not.exist");
-        cy.button(IMPLICIT_ACTION_NAME).should("not.exist");
-        cy.findByText("Not found").should("be.visible");
-      });
-    });
-
     it("should respect permissions", () => {
       // Enabling actions for sample database as well
       // to test database picker behavior in the action editor
@@ -381,6 +295,163 @@ describe(
   },
 );
 
+['postgres', 'mysql'].forEach((dialect) => {
+  describe(`Write actions on model detail page (${dialect})`, () => {
+
+    beforeEach(() => {
+      cy.intercept("GET", "/api/card/*").as("getModel");
+
+      resetTestTable({ type: dialect, table: WRITABLE_TEST_TABLE });
+      restore(`${dialect}-writable`);
+      cy.signInAsAdmin();
+      resyncDatabase({ dbId: WRITABLE_DB_ID, tableName: WRITABLE_TEST_TABLE });
+
+      createModelFromTableName({ tableName: WRITABLE_TEST_TABLE, idAlias: "writableModelId" });
+    });
+
+    it("should allow action execution from the model detail page", () => {
+      queryWritableDB(
+        `SELECT * FROM ${WRITABLE_TEST_TABLE} WHERE id = 1`,
+        dialect,
+      ).then(result => {
+        const row = result.rows[0];
+        expect(row.score).to.equal(0);
+      });
+
+      cy.get("@writableModelId").then(modelId => {
+        createAction({
+          ...SAMPLE_WRITABLE_QUERY_ACTION,
+          model_id: modelId,
+        });
+        cy.visit(`/model/${modelId}/detail/actions`);
+        cy.wait("@getModel");
+      });
+
+      runActionFor(SAMPLE_QUERY_ACTION.name);
+
+      modal().within(() => {
+        cy.findByLabelText(TEST_PARAMETER.name).type("1");
+        cy.button(SAMPLE_QUERY_ACTION.name).click();
+      });
+
+      cy.findByText(`${SAMPLE_QUERY_ACTION.name} ran successfully`).should(
+        "be.visible",
+      );
+
+      queryWritableDB(
+        `SELECT * FROM ${WRITABLE_TEST_TABLE} WHERE id = 1`,
+        dialect,
+      ).then(result => {
+        const row = result.rows[0];
+
+        expect(row.score).to.equal(22);
+      });
+    });
+
+    it("should allow public sharing of actions and execution of public actions", () => {
+      const IMPLICIT_ACTION_NAME = "Update";
+
+      cy.get("@writableModelId").then(modelId => {
+        createAction({
+          ...SAMPLE_WRITABLE_QUERY_ACTION,
+          model_id: modelId,
+        });
+        createAction({
+          type: "implicit",
+          kind: "row/update",
+          name: IMPLICIT_ACTION_NAME,
+          model_id: modelId,
+        });
+        cy.visit(`/model/${modelId}/detail/actions`);
+        cy.wait("@getModel");
+      });
+
+      enableSharingFor(SAMPLE_WRITABLE_QUERY_ACTION.name, {
+        publicUrlAlias: "queryActionPublicUrl",
+      });
+      enableSharingFor(IMPLICIT_ACTION_NAME, {
+        publicUrlAlias: "implicitActionPublicUrl",
+      });
+
+      cy.signOut();
+
+      cy.get("@queryActionPublicUrl").then(url => {
+        cy.visit(url);
+        cy.findByLabelText(TEST_PARAMETER.name).type("1");
+        cy.button(SAMPLE_QUERY_ACTION.name).click();
+        cy.findByText(`${SAMPLE_WRITABLE_QUERY_ACTION.name} ran successfully`).should(
+          "be.visible",
+        );
+        cy.findByRole("form").should("not.exist");
+        cy.button(SAMPLE_QUERY_ACTION.name).should("not.exist");
+
+        queryWritableDB(
+          `SELECT * FROM ${WRITABLE_TEST_TABLE} WHERE id = 1`,
+          dialect,
+        ).then(result => {
+          const row = result.rows[0];
+
+          expect(row.score).to.equal(22);
+        });
+      });
+
+      cy.get("@implicitActionPublicUrl").then(url => {
+        cy.visit(url);
+
+        // team 2 has 10 points, let's give them more
+        cy.findByLabelText("Id").type("2");
+        cy.findByLabelText(/score/i).type("16");
+        cy.findByLabelText(/team name/i).type("Bouncy Bears");
+
+
+        cy.button(IMPLICIT_ACTION_NAME).click();
+        cy.findByText(`${IMPLICIT_ACTION_NAME} ran successfully`).should(
+          "be.visible",
+        );
+        cy.findByRole("form").should("not.exist");
+        cy.button(IMPLICIT_ACTION_NAME).should("not.exist");
+
+        queryWritableDB(
+          `SELECT * FROM ${WRITABLE_TEST_TABLE} WHERE id = 2`,
+          dialect,
+        ).then(result => {
+          const row = result.rows[0];
+
+          expect(row.score).to.equal(16);
+          expect(row.team_name).to.equal("Bouncy Bears");
+          // should not mutate form fields that we don't touch
+          expect(row.status).to.not.be.a('null');
+        });
+      });
+
+      cy.signInAsAdmin();
+      cy.get("@writableModelId").then(modelId => {
+        cy.visit(`/model/${modelId}/detail/actions`);
+        cy.wait("@getModel");
+      });
+
+      disableSharingFor(SAMPLE_QUERY_ACTION.name);
+      disableSharingFor(IMPLICIT_ACTION_NAME);
+
+      cy.signOut();
+
+      cy.get("@queryActionPublicUrl").then(url => {
+        cy.visit(url);
+        cy.findByRole("form").should("not.exist");
+        cy.button(SAMPLE_QUERY_ACTION.name).should("not.exist");
+        cy.findByText("Not found").should("be.visible");
+      });
+
+      cy.get("@implicitActionPublicUrl").then(url => {
+        cy.visit(url);
+        cy.findByRole("form").should("not.exist");
+        cy.button(SAMPLE_QUERY_ACTION.name).should("not.exist");
+        cy.findByText("Not found").should("be.visible");
+      });
+    });
+  });
+});
+
 function runActionFor(actionName) {
   cy.findByRole("listitem", { name: actionName }).within(() => {
     cy.icon("play").click();