diff --git a/frontend/src/metabase/lib/formatting/numbers.tsx b/frontend/src/metabase/lib/formatting/numbers.tsx
index c9279fc427193e83cba4bd816c079790a063b736..4b6ab5ce99a3d82677df4cb5c509f2d0082607c0 100644
--- a/frontend/src/metabase/lib/formatting/numbers.tsx
+++ b/frontend/src/metabase/lib/formatting/numbers.tsx
@@ -24,7 +24,7 @@ interface FormatNumberOptionsType {
   negativeInParentheses?: boolean;
   number_separators?: string;
   number_style?: string;
-  scale?: number;
+  scale?: string;
   type?: string;
 }
 
@@ -83,12 +83,7 @@ export function formatNumber(
   } else {
     try {
       let nf;
-      if (
-        number < 1 &&
-        number > -1 &&
-        options.decimals == null &&
-        options.number_style !== "percent"
-      ) {
+      if (number < 1 && number > -1 && options.decimals == null) {
         // NOTE: special case to match existing behavior for small numbers, use
         // max significant digits instead of max fraction digits
         nf = numberFormatterForOptions({
diff --git a/frontend/src/metabase/static-viz/lib/numbers.ts b/frontend/src/metabase/static-viz/lib/numbers.ts
index ded9337bf66be8c5466158d3ffe0319202758c55..4f20c87d58b5037ebd6867e2df9f80b8b4c388bd 100644
--- a/frontend/src/metabase/static-viz/lib/numbers.ts
+++ b/frontend/src/metabase/static-viz/lib/numbers.ts
@@ -1,5 +1,4 @@
 import { merge } from "icepick";
-import { formatNumber as appFormatNumber } from "metabase/lib/formatting/numbers";
 
 export type NumberFormatOptions = {
   number_style?: "currency" | "decimal" | "scientific" | "percentage";
@@ -25,9 +24,74 @@ const DEFAULT_OPTIONS = {
 };
 
 export const formatNumber = (number: number, options?: NumberFormatOptions) => {
-  const { prefix, suffix } = { ...DEFAULT_OPTIONS, ...options };
+  const {
+    number_style,
+    currency,
+    currency_style,
+    number_separators: [decimal_separator, grouping_separator],
+    decimals,
+    scale,
+    prefix,
+    suffix,
+    compact,
+  } = handleSmallNumberFormat(number, { ...DEFAULT_OPTIONS, ...options });
 
-  return `${prefix}${appFormatNumber(number, options)}${suffix}`;
+  function createFormat(compact?: boolean) {
+    if (compact) {
+      return new Intl.NumberFormat("en", {
+        style: number_style !== "scientific" ? number_style : "decimal",
+        notation: "compact",
+        compactDisplay: "short",
+        currency: currency,
+        currencyDisplay: currency_style,
+        useGrouping: true,
+        maximumFractionDigits: decimals != null ? decimals : 2,
+      });
+    }
+
+    return new Intl.NumberFormat("en", {
+      style: number_style !== "scientific" ? number_style : "decimal",
+      notation: number_style !== "scientific" ? "standard" : "scientific",
+      currency: currency,
+      currencyDisplay: currency_style,
+      useGrouping: true,
+      minimumFractionDigits: decimals,
+      maximumFractionDigits: decimals != null ? decimals : 2,
+    });
+  }
+
+  const format = createFormat(compact);
+
+  const separatorMap = {
+    ",": grouping_separator || "",
+    ".": decimal_separator,
+  };
+  const formattedNumber = format
+    .format(number * scale)
+    .replace(/,|\./g, separator => separatorMap[separator as "." | ","]);
+
+  return `${prefix}${formattedNumber}${suffix}`;
+};
+
+// Simple hack to handle small decimal numbers (0-1)
+function handleSmallNumberFormat<T>(value: number, options: T): T {
+  const hasAtLeastThreeDecimalPoints = Math.abs(value) < 0.01;
+  if (hasAtLeastThreeDecimalPoints && Math.abs(value) > 0) {
+    options = maybeMerge(options, {
+      compact: true,
+      decimals: 4,
+    });
+  }
+
+  return options;
+}
+
+const maybeMerge = <T, S1>(collection: T, object: S1) => {
+  if (collection == null) {
+    return collection;
+  }
+
+  return merge(collection, object);
 };
 
 export const formatPercent = (percent: number) =>
diff --git a/frontend/src/metabase/static-viz/lib/numbers.unit.spec.js b/frontend/src/metabase/static-viz/lib/numbers.unit.spec.js
index 889d0dacd64fbd3bca7efaf199eec1761b47b954..acf4be395e791f48cc8c7f6fa2f3885874affb88 100644
--- a/frontend/src/metabase/static-viz/lib/numbers.unit.spec.js
+++ b/frontend/src/metabase/static-viz/lib/numbers.unit.spec.js
@@ -46,7 +46,7 @@ describe("formatNumber", () => {
       number_style: "scientific",
     });
 
-    expect(text).toEqual("1.2e+3");
+    expect(text).toEqual("1.2E3");
   });
 
   it("should format a number with custom number separators", () => {
diff --git a/frontend/test/metabase/lib/formatting.unit.spec.js b/frontend/test/metabase/lib/formatting.unit.spec.js
index f2a53d0c36c88213b07c520f6b73f2f8199378f8..a39b9cfb2cd22b3639859cf1eb69f0ba66058250 100644
--- a/frontend/test/metabase/lib/formatting.unit.spec.js
+++ b/frontend/test/metabase/lib/formatting.unit.spec.js
@@ -103,12 +103,6 @@ describe("formatting", () => {
       });
       it("should format percentages", () => {
         const options = { compact: true, number_style: "percent" };
-        expect(formatNumber(0.867, { number_style: "percent" })).toEqual(
-          "86.7%",
-        );
-        expect(formatNumber(1.2345, { number_style: "percent" })).toEqual(
-          "123.45%",
-        );
         expect(formatNumber(0, options)).toEqual("0%");
         expect(formatNumber(0.001, options)).toEqual("0.1%");
         expect(formatNumber(0.0001, options)).toEqual("0.01%");