diff --git a/changelog/entries/unreleased/bug/2289_higher_than_and_lower_than_frontend_filters_are_not_working_.json b/changelog/entries/unreleased/bug/2289_higher_than_and_lower_than_frontend_filters_are_not_working_.json
new file mode 100644
index 000000000..2fa230e52
--- /dev/null
+++ b/changelog/entries/unreleased/bug/2289_higher_than_and_lower_than_frontend_filters_are_not_working_.json
@@ -0,0 +1,7 @@
+{
+    "type": "bug",
+    "message": "Fix higher_than and lower_than frontend view filters for formula fields.",
+    "issue_number": 2289,
+    "bullet_points": [],
+    "created_at": "2024-01-17"
+}
\ No newline at end of file
diff --git a/web-frontend/modules/database/components/row/ForeignRowEditModal.vue b/web-frontend/modules/database/components/row/ForeignRowEditModal.vue
index f49130f14..aced27965 100644
--- a/web-frontend/modules/database/components/row/ForeignRowEditModal.vue
+++ b/web-frontend/modules/database/components/row/ForeignRowEditModal.vue
@@ -144,8 +144,6 @@ export default {
           this.$registry
         )
 
-      console.log(newRowValues)
-
       this.$store.dispatch('rowModal/updated', {
         tableId: this.tableId,
         values: newRowValues,
diff --git a/web-frontend/modules/database/components/row/RowHistoryFieldDuration.vue b/web-frontend/modules/database/components/row/RowHistoryFieldDuration.vue
index 817379999..7e4b7f02b 100644
--- a/web-frontend/modules/database/components/row/RowHistoryFieldDuration.vue
+++ b/web-frontend/modules/database/components/row/RowHistoryFieldDuration.vue
@@ -36,7 +36,11 @@ export default {
   methods: {
     formattedDuration(value) {
       const metadata = this.entry.fields_metadata[this.fieldIdentifier]
-      return DurationFieldType.formatValue(metadata, value)
+      const durationFieldType = this.$registry.get(
+        'field',
+        DurationFieldType.getType()
+      )
+      return durationFieldType.formatValue(metadata, value)
     },
   },
 }
diff --git a/web-frontend/modules/database/components/view/grid/fields/FunctionalGridViewFieldDuration.vue b/web-frontend/modules/database/components/view/grid/fields/FunctionalGridViewFieldDuration.vue
index 221d44742..40af413bd 100644
--- a/web-frontend/modules/database/components/view/grid/fields/FunctionalGridViewFieldDuration.vue
+++ b/web-frontend/modules/database/components/view/grid/fields/FunctionalGridViewFieldDuration.vue
@@ -7,14 +7,14 @@
 </template>
 
 <script>
-import { DurationFieldType } from '@baserow/modules/database/fieldTypes'
+import { formatDurationValue } from '@baserow/modules/database/utils/duration'
 
 export default {
   name: 'FunctionalGridViewFieldDuration',
   functional: true,
   methods: {
     formatValue(field, value) {
-      return DurationFieldType.formatValue(field, value)
+      return formatDurationValue(value, field.duration_format)
     },
   },
 }
diff --git a/web-frontend/modules/database/fieldTypes.js b/web-frontend/modules/database/fieldTypes.js
index b8ab30c15..8f6a4d250 100644
--- a/web-frontend/modules/database/fieldTypes.js
+++ b/web-frontend/modules/database/fieldTypes.js
@@ -741,7 +741,7 @@ export class FieldType extends Registerable {
    * moment object, or a duration field can accept a string like '1:30' to
    * convert it to a number of seconds.
    */
-  static parseInputValue(field, value) {
+  parseInputValue(field, value) {
     return value
   }
 }
@@ -1351,7 +1351,7 @@ export class NumberFieldType extends FieldType {
     return true
   }
 
-  static parseInputValue(field, value) {
+  parseInputValue(field, value) {
     return parseFloat(value)
   }
 }
@@ -1683,8 +1683,8 @@ class BaseDateFieldType extends FieldType {
    * correct format for the field. If it can't be parsed null is returned.
    */
   prepareValueForPaste(field, clipboardData, richClipboardData) {
-    const dateValue = DateFieldType.parseInputValue(field, clipboardData || '')
-    return DateFieldType.formatDate(field, dateValue)
+    const dateValue = this.parseInputValue(field, clipboardData || '')
+    return this.formatValue(field, dateValue)
   }
 
   /**
@@ -1724,7 +1724,7 @@ class BaseDateFieldType extends FieldType {
     return formats
   }
 
-  static parseInputValue(field, dateString) {
+  parseInputValue(field, dateString) {
     const formats = DateFieldType.getDateFormatsOptionsForValue(
       field,
       dateString
@@ -1751,8 +1751,8 @@ class BaseDateFieldType extends FieldType {
     return date
   }
 
-  static formatDate(field, date) {
-    const momentDate = moment.utc(date)
+  formatValue(field, value) {
+    const momentDate = moment.utc(value)
     if (momentDate.isValid()) {
       return field.date_include_time
         ? momentDate.format()
@@ -1838,9 +1838,9 @@ export class DateFieldType extends BaseDateFieldType {
   }
 
   parseQueryParameter(field, value) {
-    return DateFieldType.formatDate(
+    return this.formatValue(
       field.field,
-      DateFieldType.parseInputValue(field.field, value)
+      this.parseInputValue(field.field, value)
     )
   }
 }
@@ -2280,11 +2280,11 @@ export class DurationFieldType extends FieldType {
   }
 
   parseQueryParameter(field, value, options) {
-    return DurationFieldType.parseInputValue(field, value)
+    return this.parseInputValue(field.field, value)
   }
 
   toSearchableString(field, value, delimiter = ', ') {
-    return DurationFieldType.formatValue(field, value)
+    return this.formatValue(field, value)
   }
 
   getSort(name, order) {
@@ -2350,22 +2350,22 @@ export class DurationFieldType extends FieldType {
     return RowHistoryFieldDuration
   }
 
-  static formatValue(field, value) {
+  formatValue(field, value) {
     return formatDurationValue(value, field.duration_format)
   }
 
-  static parseInputValue(field, value) {
+  parseInputValue(field, value) {
     const format = field.duration_format
     const preparedValue = parseDurationValue(value, format)
     return roundDurationValueToFormat(preparedValue, format)
   }
 
   toHumanReadableString(field, value, delimiter = ', ') {
-    return DurationFieldType.formatValue(field, value)
+    return this.formatValue(field, value)
   }
 
   prepareValueForCopy(field, value) {
-    return DurationFieldType.formatValue(field, value)
+    return this.formatValue(field, value)
   }
 
   prepareRichValueForCopy(field, value) {
@@ -2376,7 +2376,7 @@ export class DurationFieldType extends FieldType {
     if (richClipboardData && isNumeric(richClipboardData)) {
       return richClipboardData
     }
-    return DurationFieldType.parseInputValue(field, clipboardData)
+    return this.parseInputValue(field, clipboardData)
   }
 
   getCanGroupByInView(field) {
@@ -3543,6 +3543,14 @@ export class FormulaFieldType extends FieldType {
     const subType = this.app.$registry.get('formula_type', field.formula_type)
     return subType.canGroupByInView(field)
   }
+
+  parseInputValue(field, value) {
+    const underlyingFieldType = this.app.$registry.get(
+      'field',
+      this._mapFormulaTypeToFieldType(field.formula_type)
+    )
+    return underlyingFieldType.parseInputValue(field, value)
+  }
 }
 
 export class CountFieldType extends FormulaFieldType {
diff --git a/web-frontend/modules/database/mixins/durationField.js b/web-frontend/modules/database/mixins/durationField.js
index eadd75f35..9a509ebb9 100644
--- a/web-frontend/modules/database/mixins/durationField.js
+++ b/web-frontend/modules/database/mixins/durationField.js
@@ -12,6 +12,11 @@ export default {
       formattedValue: '',
     }
   },
+  computed: {
+    fieldType() {
+      return this.$registry.get('field', DurationFieldType.getType())
+    },
+  },
   watch: {
     value(value) {
       this.updateFormattedValue(this.field, value)
@@ -31,7 +36,7 @@ export default {
       return this.errorMsg
     },
     formatValue(field, value) {
-      return DurationFieldType.formatValue(field, value)
+      return this.fieldType.formatValue(field, value)
     },
     updateFormattedValue(field, value) {
       this.formattedValue = this.formatValue(field, value)
@@ -41,7 +46,7 @@ export default {
       if (this.errorMsg !== null) {
         return
       }
-      const newCopy = DurationFieldType.parseInputValue(field, value)
+      const newCopy = this.fieldType.parseInputValue(field, value)
       if (newCopy !== this.copy) {
         this.copy = newCopy
         return newCopy
diff --git a/web-frontend/modules/database/viewFilters.js b/web-frontend/modules/database/viewFilters.js
index b3d4ad916..91fc2ec91 100644
--- a/web-frontend/modules/database/viewFilters.js
+++ b/web-frontend/modules/database/viewFilters.js
@@ -1341,13 +1341,9 @@ export class HigherThanViewFilterType extends ViewFilterType {
       return true
     }
 
-    rowValue = fieldType.constructor.parseInputValue(field, rowValue)
-    filterValue = fieldType.constructor.parseInputValue(field, filterValue)
-    return (
-      Number.isFinite(rowValue) &&
-      Number.isFinite(filterValue) &&
-      rowValue > filterValue
-    )
+    const rowVal = fieldType.parseInputValue(field, rowValue)
+    const fltVal = fieldType.parseInputValue(field, filterValue)
+    return Number.isFinite(rowVal) && Number.isFinite(fltVal) && rowVal > fltVal
   }
 }
 
@@ -1388,13 +1384,9 @@ export class LowerThanViewFilterType extends ViewFilterType {
       return true
     }
 
-    rowValue = fieldType.constructor.parseInputValue(field, rowValue)
-    filterValue = fieldType.constructor.parseInputValue(field, filterValue)
-    return (
-      Number.isFinite(rowValue) &&
-      Number.isFinite(filterValue) &&
-      rowValue < filterValue
-    )
+    const rowVal = fieldType.parseInputValue(field, rowValue)
+    const fltVal = fieldType.parseInputValue(field, filterValue)
+    return Number.isFinite(rowVal) && Number.isFinite(fltVal) && rowVal < fltVal
   }
 }
 
diff --git a/web-frontend/test/unit/database/fieldTypes.spec.js b/web-frontend/test/unit/database/fieldTypes.spec.js
index d3b10f9a8..cea971cc5 100644
--- a/web-frontend/test/unit/database/fieldTypes.spec.js
+++ b/web-frontend/test/unit/database/fieldTypes.spec.js
@@ -603,17 +603,20 @@ const queryParametersForParsing = [
   },
   {
     fieldType: new DurationFieldType(),
-    input: { value: '1:01', field: { duration_format: 'h:mm' } },
+    input: { value: '1:01', field: { field: { duration_format: 'h:mm' } } },
     output: 3660,
   },
   {
     fieldType: new DurationFieldType(),
-    input: { value: '1:01:01', field: { duration_format: 'h:mm:ss' } },
+    input: {
+      value: '1:01:01',
+      field: { field: { duration_format: 'h:mm:ss' } },
+    },
     output: 3661,
   },
   {
     fieldType: new DurationFieldType(),
-    input: { value: 61, field: { duration_format: 'h:mm' } },
+    input: { value: 61, field: { field: { duration_format: 'h:mm' } } },
     output: 60, // the value is rounded according to the duration format
   },
 ]
diff --git a/web-frontend/test/unit/database/viewFiltersMatch.spec.js b/web-frontend/test/unit/database/viewFiltersMatch.spec.js
index 0de5101ca..eaf485957 100644
--- a/web-frontend/test/unit/database/viewFiltersMatch.spec.js
+++ b/web-frontend/test/unit/database/viewFiltersMatch.spec.js
@@ -31,7 +31,11 @@ import {
   HigherThanViewFilterType,
   LowerThanViewFilterType,
 } from '@baserow/modules/database/viewFilters'
-import { DurationFieldType } from '@baserow/modules/database/fieldTypes'
+import {
+  DurationFieldType,
+  NumberFieldType,
+  FormulaFieldType,
+} from '@baserow/modules/database/fieldTypes'
 
 const dateBeforeCases = [
   {
@@ -1126,6 +1130,42 @@ const durationLowerThanCases = [
   },
 ]
 
+const numberValueIsHigherThanCases = [
+  {
+    rowValue: 2,
+    filterValue: 0,
+    expected: true,
+  },
+  {
+    rowValue: null,
+    filterValue: 0,
+    expected: false,
+  },
+  {
+    rowValue: 0,
+    filterValue: '0',
+    expected: false,
+  },
+]
+
+const numberValueIsLowerThanCases = [
+  {
+    rowValue: 1,
+    filterValue: '2',
+    expected: true,
+  },
+  {
+    rowValue: null,
+    filterValue: 0,
+    expected: false,
+  },
+  {
+    rowValue: 0,
+    filterValue: '0',
+    expected: false,
+  },
+]
+
 describe('All Tests', () => {
   let testApp = null
 
@@ -1405,10 +1445,28 @@ describe('All Tests', () => {
     ).toBe(true)
   })
 
-  test.each(durationHigherThanCases)('HigherThanFilterType', (values) => {
-    const fieldType = new DurationFieldType()
+  test.each(durationHigherThanCases)(
+    'DurationHigherThanFilterType',
+    (values) => {
+      const fieldType = new DurationFieldType({
+        app: testApp,
+      })
+      const { field } = values.context
+      const result = new HigherThanViewFilterType({ app: testApp }).matches(
+        values.rowValue,
+        values.filterValue,
+        field,
+        fieldType
+      )
+      expect(result).toBe(values.expected)
+    }
+  )
+
+  test.each(durationLowerThanCases)('DurationLowerThanFilterType', (values) => {
+    const app = testApp.getApp()
+    const fieldType = new DurationFieldType({ app })
     const { field } = values.context
-    const result = new HigherThanViewFilterType({ app: testApp }).matches(
+    const result = new LowerThanViewFilterType({ app }).matches(
       values.rowValue,
       values.filterValue,
       field,
@@ -1417,15 +1475,59 @@ describe('All Tests', () => {
     expect(result).toBe(values.expected)
   })
 
-  test.each(durationLowerThanCases)('LowerThanFilterType', (values) => {
-    const fieldType = new DurationFieldType()
-    const { field } = values.context
-    const result = new LowerThanViewFilterType({ app: testApp }).matches(
-      values.rowValue,
-      values.filterValue,
-      field,
-      fieldType
-    )
-    expect(result).toBe(values.expected)
-  })
+  test.each(numberValueIsHigherThanCases)(
+    'NumberHigherThanFilterType',
+    (values) => {
+      const app = testApp.getApp()
+      const result = new HigherThanViewFilterType({ app }).matches(
+        values.rowValue,
+        values.filterValue,
+        { type: 'number' },
+        new NumberFieldType({ app })
+      )
+      expect(result).toBe(values.expected)
+    }
+  )
+
+  test.each(numberValueIsHigherThanCases)(
+    'FormulaNumberHigherThanFilterType',
+    (values) => {
+      const app = testApp.getApp()
+      const result = new HigherThanViewFilterType({ app }).matches(
+        values.rowValue,
+        values.filterValue,
+        { type: 'formula', formula_type: 'number' },
+        new FormulaFieldType({ app })
+      )
+      expect(result).toBe(values.expected)
+    }
+  )
+
+  test.each(numberValueIsLowerThanCases)(
+    'NumberLowerThanFilterType',
+    (values) => {
+      const app = testApp.getApp()
+      const result = new LowerThanViewFilterType({ app }).matches(
+        values.rowValue,
+        values.filterValue,
+        { type: 'number' },
+        new NumberFieldType({ app })
+      )
+      expect(result).toBe(values.expected)
+    }
+  )
+
+  test.each(numberValueIsLowerThanCases)(
+    'FormulaNumberLowerThanFilterType',
+    (values) => {
+      const app = testApp.getApp()
+      const result = new LowerThanViewFilterType({ app }).matches(
+        values.rowValue,
+        values.filterValue,
+        { type: 'formula', formula_type: 'number' },
+        new FormulaFieldType({ app })
+      )
+      expect(result).toBe(values.expected)
+    }
+  )
 })