diff --git a/modules/drivers/googleanalytics/test/metabase/driver/googleanalytics_test.clj b/modules/drivers/googleanalytics/test/metabase/driver/googleanalytics_test.clj
index ff5d155e67973be6a05e2d4856a85d6ca646c00a..236a65fb75c6b3a3c23e339c3c53c9236f4afeba 100644
--- a/modules/drivers/googleanalytics/test/metabase/driver/googleanalytics_test.clj
+++ b/modules/drivers/googleanalytics/test/metabase/driver/googleanalytics_test.clj
@@ -301,6 +301,7 @@
                                                          :name              "ga:eventLabel"
                                                          :settings          nil
                                                          :source            :breakout
+                                                         :nfc_path          nil
                                                          :parent_id         nil
                                                          :visibility_type   :normal
                                                          :display_name      "ga:eventLabel"
diff --git a/modules/drivers/redshift/test/metabase/driver/redshift_test.clj b/modules/drivers/redshift/test/metabase/driver/redshift_test.clj
index ae0509e3c50ac60c78a042a09297137c8a137545..bc7e85cbbb8206b16f5482a309d9e64abd8df2aa 100644
--- a/modules/drivers/redshift/test/metabase/driver/redshift_test.clj
+++ b/modules/drivers/redshift/test/metabase/driver/redshift_test.clj
@@ -121,6 +121,7 @@
               :settings        nil
               :source          :fields
               :field_ref       [:field (mt/id :extsales :buyerid) nil]
+              :nfc_path        nil
               :parent_id       nil
               :id              (mt/id :extsales :buyerid)
               :visibility_type :normal
@@ -135,6 +136,7 @@
               :settings        nil
               :source          :fields
               :field_ref       [:field (mt/id :extsales :salesid) nil]
+              :nfc_path        nil
               :parent_id       nil
               :id              (mt/id :extsales :salesid)
               :visibility_type :normal
diff --git a/resources/migrations/000_migrations.yaml b/resources/migrations/000_migrations.yaml
index 76f08148d00686bfa25a8d3646c3dde8ae83f460..94743f5fc82d6c85b09e783028c14c37f0b54b0a 100644
--- a/resources/migrations/000_migrations.yaml
+++ b/resources/migrations/000_migrations.yaml
@@ -11238,6 +11238,21 @@ databaseChangeLog:
                     AND db.object = p.object
               WHERE p.object IS NULL;
 
+  - changeSet:
+      id: v43.00-043
+      author: howonlee
+      comment: Added 0.43.0 - Nested field columns in fields
+      changes:
+        - addColumn:
+            columns:
+            - column:
+                remarks: Nested field column paths, flattened
+                name: nfc_path
+                type: varchar(254)
+                constraints:
+                  nullable: true
+            tableName: metabase_field
+
   - changeSet:
       id: v43.00-044
       author: noahmoss
diff --git a/src/metabase/driver/postgres.clj b/src/metabase/driver/postgres.clj
index c2a75eca49b9c5b4d892a311f3a21fd5902ffcc2..8b3c0d683423e8518f26a37f0aab37e0aaa52c9c 100644
--- a/src/metabase/driver/postgres.clj
+++ b/src/metabase/driver/postgres.clj
@@ -32,6 +32,8 @@
 
 (driver/register! :postgres, :parent :sql-jdbc)
 
+(defmethod driver/database-supports? [:postgres :nested-field-columns] [_ _ _] true)
+
 ;;; +----------------------------------------------------------------------------------------------------------------+
 ;;; |                                             metabase.driver impls                                              |
 ;;; +----------------------------------------------------------------------------------------------------------------+
@@ -342,14 +344,27 @@
     (pretty [_]
       (format "%s::%s" (pr-str expr) (name psql-type)))))
 
+(defn- json-query [identifier nfc-path]
+  (letfn [(handle-name [x] (if (number? x) (str x) (name x)))]
+    (apply hsql/call [:json_extract_path_text
+                      (hx/cast :json (keyword (first nfc-path)))
+                      (mapv #(hx/cast :text (handle-name %)) (rest nfc-path))])))
+
 (defmethod sql.qp/->honeysql [:postgres :field]
   [driver [_ id-or-name _opts :as clause]]
-  (let [{database-type :database_type} (when (integer? id-or-name)
-                                         (qp.store/field id-or-name))
+  (let [stored-field (when (integer? id-or-name)
+                       (qp.store/field id-or-name))
         parent-method (get-method sql.qp/->honeysql [:sql :field])
-        identifier    (parent-method driver clause)]
-    (if (= database-type "money")
+        identifier    (parent-method driver clause)
+        nfc-path      (:nfc_path stored-field)]
+    (cond
+      (= (:database_type stored-field) "money")
       (pg-conversion identifier :numeric)
+
+      (some? nfc-path)
+      (json-query identifier nfc-path)
+
+      :else
       identifier)))
 
 (defmethod unprepare/unprepare-value [:postgres Date]
diff --git a/src/metabase/models/field.clj b/src/metabase/models/field.clj
index 0569206769d70fa94adbecdaee8a546cd7324379..1054532fb05993d7e2730cef5297c4407efb2fd9 100644
--- a/src/metabase/models/field.clj
+++ b/src/metabase/models/field.clj
@@ -172,7 +172,8 @@
                                        :visibility_type   :keyword
                                        :has_field_values  :keyword
                                        :fingerprint       :json-for-fingerprints
-                                       :settings          :json})
+                                       :settings          :json
+                                       :nfc_path          :json})
           :properties     (constantly {:timestamped? true})
           :pre-insert     pre-insert})
 
diff --git a/src/metabase/query_processor/middleware/add_source_metadata.clj b/src/metabase/query_processor/middleware/add_source_metadata.clj
index 0083abe5f6d551f2eecc2faf9d8d12ece8d26e8a..2b3024964a5b3ce5efe3204b11fa5f9a3f2a7d7b 100644
--- a/src/metabase/query_processor/middleware/add_source_metadata.clj
+++ b/src/metabase/query_processor/middleware/add_source_metadata.clj
@@ -56,7 +56,7 @@
                    :query    (assoc-in source-query [:middleware :disable-remaps?] true)}))]
       (for [col cols]
         (select-keys col [:name :id :table_id :display_name :base_type :effective_type :coercion_strategy
-                          :semantic_type :unit :fingerprint :settings :source_alias :field_ref :parent_id])))
+                          :semantic_type :unit :fingerprint :settings :source_alias :field_ref :nfc_path :parent_id])))
     (catch Throwable e
       (log/error e (str (trs "Error determining expected columns for query: {0}" (ex-message e))))
       nil)))
diff --git a/src/metabase/query_processor/store.clj b/src/metabase/query_processor/store.clj
index 934b3a63bead66afb2ab40b0b6cf4a891abe86bc..84b4e01544c2d09e4b1bd7d1e6c52f0172f89081 100644
--- a/src/metabase/query_processor/store.clj
+++ b/src/metabase/query_processor/store.clj
@@ -96,6 +96,7 @@
    :fingerprint
    :id
    :name
+   :nfc_path
    :parent_id
    :semantic_type
    :settings
@@ -117,6 +118,7 @@
     :semantic_type                      (s/maybe su/FieldSemanticOrRelationType)
     :fingerprint                        (s/maybe su/Map)
     :parent_id                          (s/maybe su/IntGreaterThanZero)
+    :nfc_path                           (s/maybe [su/NonBlankString])
     s/Any                               s/Any}))
 
 
diff --git a/src/metabase/sync/fetch_metadata.clj b/src/metabase/sync/fetch_metadata.clj
index 1841b1051c5adf63a10b1134c33e82cfad4b7dcb..e5f2b1eae14dd161e8a67f483ba1b4b753502dd3 100644
--- a/src/metabase/sync/fetch_metadata.clj
+++ b/src/metabase/sync/fetch_metadata.clj
@@ -3,6 +3,7 @@
   tables, schemas, and fields, and their types. For example, with SQL databases, these functions use the JDBC
   DatabaseMetaData to get this information."
   (:require [metabase.driver :as driver]
+            [metabase.driver.sql-jdbc.sync :as sql-jdbc.sync]
             [metabase.driver.util :as driver.u]
             [metabase.sync.interface :as i]
             [schema.core :as s]))
@@ -23,3 +24,10 @@
   (let [driver (driver.u/database->driver database)]
     (when (driver/supports? driver :foreign-keys)
       (driver/describe-table-fks driver database table))))
+
+(s/defn nfc-metadata :- (s/maybe #{i/TableMetadataField})
+  "Get information about the nested field column fields within `table`."
+  [database :- i/DatabaseInstance, table :- i/TableInstance]
+  (let [driver (driver.u/database->driver database)]
+    (when (driver/supports? driver :nested-field-columns)
+      (sql-jdbc.sync/describe-nested-field-columns driver database table))))
diff --git a/src/metabase/sync/interface.clj b/src/metabase/sync/interface.clj
index bfab0baeb2faf5d98d93c5b6f1f9917519330cc5..19c3f9f252ee587618b57a65f0935ce8b422fca9 100644
--- a/src/metabase/sync/interface.clj
+++ b/src/metabase/sync/interface.clj
@@ -32,6 +32,7 @@
    (s/optional-key :field-comment)     (s/maybe su/NonBlankString)
    (s/optional-key :pk?)               s/Bool
    (s/optional-key :nested-fields)     #{(s/recursive #'TableMetadataField)}
+   (s/optional-key :nfc-path)          [s/Any]
    (s/optional-key :custom)            {s/Any s/Any}
    ;; for future backwards compatability, when adding things
    s/Keyword                           s/Any})
diff --git a/src/metabase/sync/sync_metadata/fields/fetch_metadata.clj b/src/metabase/sync/sync_metadata/fields/fetch_metadata.clj
index 5080a5aa2b25bf802f5ebd0986b12e52c82241e8..fe57f568d94ca9799574f45d9364f27ccf34de1d 100644
--- a/src/metabase/sync/sync_metadata/fields/fetch_metadata.clj
+++ b/src/metabase/sync/sync_metadata/fields/fetch_metadata.clj
@@ -3,7 +3,9 @@
   about Fields in a Table, and for fetching the DB metadata itself. This metadata is used by the logic in other
   `metabase.sync.sync-metadata.fields.*` namespaces to determine what sync operations need to be performed by
   comparing the differences in the two sets of Metadata."
-  (:require [medley.core :as m]
+  (:require [clojure.set :as set]
+            [medley.core :as m]
+            [metabase.driver :as driver]
             [metabase.models.field :as field :refer [Field]]
             [metabase.models.table :as table]
             [metabase.sync.fetch-metadata :as fetch-metadata]
@@ -48,17 +50,6 @@
       (assoc metabase-field :nested-fields (set (for [nested-field nested-fields]
                                                   (add-nested-fields nested-field parent-id->fields)))))))
 
-(s/defn ^:private add-nested-field-columns :- common/TableMetadataFieldWithID
-  "Nested field columns are flattened, unlike the ordinary nested fields.
-  Add the pertinent nested fields to the parent column"
-  [mb-field :- common/TableMetadataFieldWithID,
-   nfc-fields :- #{common/TableMetadataFieldWithID}]
-  (let [column-fields (filter #(= (keyword (mb-field :name))
-                                  (get-in % [:nfc-path 0])) nfc-fields)]
-        (if-not (seq column-fields)
-          mb-field
-          (assoc mb-field :nested-fields (set column-fields)))))
-
 (s/defn fields->our-metadata :- #{common/TableMetadataFieldWithID}
   "Given a sequence of Metabase Fields, format them and return them in a hierachy so the format matches the one
   `db-metadata` comes back in."
@@ -75,7 +66,7 @@
   "Fetch active Fields from the Metabase application database for a given `table`."
   [table :- i/TableInstance]
  (db/select [Field :name :database_type :base_type :effective_type :coercion_strategy :semantic_type
-             :parent_id :id :description :database_position]
+             :parent_id :id :description :database_position :nfc_path]
      :table_id  (u/the-id table)
      :active    true
      {:order-by table/field-order-rule}))
@@ -94,4 +85,6 @@
   "Fetch metadata about Fields belonging to a given `table` directly from an external database by calling its driver's
   implementation of `describe-table`."
   [database :- i/DatabaseInstance table :- i/TableInstance]
-  (:fields (fetch-metadata/table-metadata database table)))
+  (cond-> (:fields (fetch-metadata/table-metadata database table))
+    (driver/database-supports? (:engine database) :nested-field-columns database)
+    (set/union (fetch-metadata/nfc-metadata database table))))
diff --git a/src/metabase/sync/sync_metadata/fields/sync_instances.clj b/src/metabase/sync/sync_metadata/fields/sync_instances.clj
index 7207bb706ebade4e1bad68c380decc9307933eb8..8163a94ad8d546bcf47df6392b81ad7084513ca7 100644
--- a/src/metabase/sync/sync_metadata/fields/sync_instances.clj
+++ b/src/metabase/sync/sync_metadata/fields/sync_instances.clj
@@ -39,7 +39,7 @@
   [table :- i/TableInstance, new-field-metadatas :- [i/TableMetadataField], parent-id :- common/ParentID]
   (when (seq new-field-metadatas)
     (db/insert-many! Field
-      (for [{:keys [database-type base-type effective-type coercion-strategy field-comment database-position], field-name :name :as field} new-field-metadatas]
+      (for [{:keys [database-type base-type effective-type coercion-strategy field-comment database-position nfc-path], field-name :name :as field} new-field-metadatas]
         (do
          (when (and effective-type
                     base-type
@@ -62,6 +62,7 @@
           :coercion_strategy (when effective-type coercion-strategy)
           :semantic_type     (common/semantic-type field)
           :parent_id         parent-id
+          :nfc_path          nfc-path
           :description       field-comment
           :position          database-position
           :database_position database-position})))))
@@ -174,7 +175,8 @@
 
 (s/defn ^:private sync-nested-field-instances! :- (s/maybe su/IntGreaterThanOrEqualToZero)
   "Recursively sync Field instances (i.e., rows in application DB) for *all* the nested Fields of all Fields in
-  `db-metadata` and `our-metadata`."
+  `db-metadata` and `our-metadata`.
+  Not for the flattened nested fields for JSON columns in normal RDBMSes (nested field columns)"
   [table        :- i/TableInstance
    db-metadata  :- #{i/TableMetadataField}
    our-metadata :- #{common/TableMetadataFieldWithID}]
diff --git a/test/metabase/driver/postgres_test.clj b/test/metabase/driver/postgres_test.clj
index d0bf486a7179cf23bb0c9509cf0d653b42d73fce..9226cbaaabaf29667714516632303413ead54d2a 100644
--- a/test/metabase/driver/postgres_test.clj
+++ b/test/metabase/driver/postgres_test.clj
@@ -285,6 +285,17 @@
         (is (= :type/SerializedJSON
                (db/select-one-field :semantic_type Field, :id (mt/id :venues :address))))))))
 
+(deftest json-query-test
+  (testing "Transforming MBQL query with JSON in it to postgres query works"
+    (is (= ["json_extract_path_text(CAST(bleh AS json), (CAST(? AS text)))" "meh"]
+           (hsql/format (#'postgres/json-query 'mlep [:bleh :meh])))))
+  (testing "What if types are weird and we have lists"
+    (is (= ["json_extract_path_text(CAST(bleh AS json), (CAST(? AS text), CAST(? AS text), CAST(? AS text)))"
+            "meh"
+            "foobar"
+            "1234"]
+           (hsql/format (#'postgres/json-query 'mlep '(:bleh "meh" :foobar 1234)))))))
+
 (deftest describe-nested-field-columns-test
   (mt/test-driver :postgres
     (testing "flattened-row"
diff --git a/test/metabase/query_processor/async_test.clj b/test/metabase/query_processor/async_test.clj
index 3bf1ecbe5f89a99116bc33912f7f51362eb23ea2..88e48dbc71738a5829a0783d13dad4337c3d687a 100644
--- a/test/metabase/query_processor/async_test.clj
+++ b/test/metabase/query_processor/async_test.clj
@@ -28,6 +28,7 @@
                :table_id          (mt/id :venues)
                :settings          nil
                :source            :fields
+               :nfc_path          nil
                :parent_id         nil
                :visibility_type   :normal
                :id                (mt/id :venues :name)
diff --git a/test/metabase/query_processor/middleware/add_source_metadata_test.clj b/test/metabase/query_processor/middleware/add_source_metadata_test.clj
index e340b6f3cb4b9a6e400ca7955e07929673be1e6d..99bcf3a4905349db41f71a79c0defb6562801ced 100644
--- a/test/metabase/query_processor/middleware/add_source_metadata_test.clj
+++ b/test/metabase/query_processor/middleware/add_source_metadata_test.clj
@@ -17,7 +17,7 @@
     (select-keys
      col
      [:id :table_id :name :display_name :base_type :effective_type :coercion_strategy
-      :semantic_type :unit :fingerprint :settings :field_ref :parent_id])))
+      :semantic_type :unit :fingerprint :settings :field_ref :nfc_path :parent_id])))
 
 (defn- venues-source-metadata
   ([]
diff --git a/test/metabase/query_processor/middleware/annotate_test.clj b/test/metabase/query_processor/middleware/annotate_test.clj
index 94f75e96e1b74e2e6ec3fc774a666d862c9b3a3a..68f1f24e86d889d23c34f3d098624c8b6dda8783 100644
--- a/test/metabase/query_processor/middleware/annotate_test.clj
+++ b/test/metabase/query_processor/middleware/annotate_test.clj
@@ -220,6 +220,7 @@
                 :name            "parent.child"
                 :settings        nil
                 :field_ref       [:field (u/the-id child) nil]
+                :nfc_path        nil
                 :parent_id       (u/the-id parent)
                 :id              (u/the-id child)
                 :visibility_type :normal
@@ -241,6 +242,7 @@
                 :name            "grandparent.parent.child"
                 :settings        nil
                 :field_ref       [:field (u/the-id child) nil]
+                :nfc_path        nil
                 :parent_id       (u/the-id parent)
                 :id              (u/the-id child)
                 :visibility_type :normal
diff --git a/test/metabase/query_processor_test.clj b/test/metabase/query_processor_test.clj
index 79d7bade959d79b8d102f7b4efaddd9deaab2e96..b25aec98cc2302ea87cb93c1831729f215420c7d 100644
--- a/test/metabase/query_processor_test.clj
+++ b/test/metabase/query_processor_test.clj
@@ -69,6 +69,7 @@
   {:description     nil
    :visibility_type :normal
    :settings        nil
+   :nfc_path        nil
    :parent_id       nil
    :source          :fields})
 
diff --git a/test/metabase/query_processor_test/nested_queries_test.clj b/test/metabase/query_processor_test/nested_queries_test.clj
index 26e16985f511a5fa1031ac0802ee89b8044a3eee..e6352720ee819c05ffb52fbeb0681f6f6d2def5e 100644
--- a/test/metabase/query_processor_test/nested_queries_test.clj
+++ b/test/metabase/query_processor_test/nested_queries_test.clj
@@ -70,7 +70,7 @@
             native-source?
             (-> (assoc :field_ref [:field "PRICE" {:base-type :type/Integer}]
                        :effective_type :type/Integer)
-                (dissoc :description :parent_id :visibility_type))
+                (dissoc :description :parent_id :nfc_path :visibility_type))
 
             (not has-source-metadata?)
             (dissoc :id :semantic_type :settings :fingerprint :table_id :coercion_strategy))
@@ -446,7 +446,7 @@
                 ;; because this field literal comes from a native query that does not include `:source-metadata` it won't have
                 ;; the usual extra keys
                 (dissoc :semantic_type :coercion_strategy :table_id
-                        :id :settings :fingerprint))
+                        :id :settings :fingerprint :nfc_path))
             (qp.test/aggregate-col :count)]
            (mt/cols
              (mt/with-temp Card [card {:dataset_query {:database (mt/id)
diff --git a/test/metabase/sync/sync_metadata/fields/fetch_metadata_test.clj b/test/metabase/sync/sync_metadata/fields/fetch_metadata_test.clj
index 6a9e446682dc47c67ef7a16599f8e67ced4dec45..05835d46b30b916d58eb80b620aed69c59995eb8 100644
--- a/test/metabase/sync/sync_metadata/fields/fetch_metadata_test.clj
+++ b/test/metabase/sync/sync_metadata/fields/fetch_metadata_test.clj
@@ -11,51 +11,6 @@
             [metabase.util :as u]
             [toucan.db :as db]))
 
-(deftest add-nested-field-columns-test
-  (testing "adds nested field columns for one field"
-    (let [our-field  {:name      "coherent_json_val"
-                      :base-type :type/*
-                      :database-type "blah",
-                      :database-position 0,
-                      :id        1}
-          nfc-fields '#{{:name               "incoherent_json_val → b",
-                          :database-type     "blah",
-                          :base-type         :type/*,
-                          :database-position 0,
-                          :id                2,
-                          :nfc-path          [:incoherent_json_val "b"]}
-                         {:name              "coherent_json_val → a",
-                          :database-type     "blah",
-                          :base-type         :type/*,
-                          :database-position 0,
-                          :id                3,
-                          :nfc-path          [:coherent_json_val "a"]}
-                         {:name              "coherent_json_val → b",
-                          :database-type     "blah",
-                          :base-type         :type/*,
-                          :database-position 0,
-                          :id                4,
-                          :nfc-path          [:coherent_json_val "b"]}}]
-      (is (= (#'sync-fields.fetch-metadata/add-nested-field-columns our-field nfc-fields)
-             {:name "coherent_json_val",
-              :base-type :type/*,
-              :database-type "blah",
-              :database-position 0,
-              :id 1,
-              :nested-fields
-              #{{:name "coherent_json_val → b",
-                 :database-type "blah",
-                 :base-type :type/*,
-                 :database-position 0,
-                 :id 4,
-                 :nfc-path [:coherent_json_val "b"]}
-                {:name "coherent_json_val → a",
-                 :database-type "blah",
-                 :base-type :type/*,
-                 :database-position 0,
-                 :id 3,
-                 :nfc-path [:coherent_json_val "a"]}}})))))
-
 ;; `our-metadata` should match up with what we have in the DB
 (deftest does-metadata-match-test
   (mt/with-temp Database [db {:engine ::toucanery/toucanery}]
diff --git a/test/metabase/test/mock/util.clj b/test/metabase/test/mock/util.clj
index 2883f4e00facac95cc47e85755e20c7038295717..9e19dcd8ff33ce3abedc569b4efca62e601414de 100644
--- a/test/metabase/test/mock/util.clj
+++ b/test/metabase/test/mock/util.clj
@@ -24,6 +24,7 @@
    :fk_target_field_id false
    :updated_at         true
    :active             true
+   :nfc_path           nil
    :parent_id          false
    :semantic_type      nil
    :id                 true