diff --git a/ios/NewExpensify.xcodeproj/project.pbxproj b/ios/NewExpensify.xcodeproj/project.pbxproj
index 1131589c72ec..c8d825589bfb 100644
--- a/ios/NewExpensify.xcodeproj/project.pbxproj
+++ b/ios/NewExpensify.xcodeproj/project.pbxproj
@@ -40,6 +40,7 @@
 		7FD73CA22B23CE9500420AF3 /* NotificationServiceExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 7FD73C9B2B23CE9500420AF3 /* NotificationServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
 		8744C5400E24E379441C04A4 /* libPods-NewExpensify.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 59A21B2405370FDDD847C813 /* libPods-NewExpensify.a */; };
 		9E17CB36A6B22BDD4BE53561 /* libPods-NotificationServiceExtension.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9196A72C11B91A52A43D6E8A /* libPods-NotificationServiceExtension.a */; };
+		AC131FBB2CF634F20010CE80 /* BackgroundTasks.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AC131FBA2CF634F20010CE80 /* BackgroundTasks.framework */; };
 		ACA597C323AA39404655647F /* libPods-NewExpensify-NewExpensifyTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EF33B19FC6A7FE676839430D /* libPods-NewExpensify-NewExpensifyTests.a */; };
 		BDB853621F354EBB84E619C2 /* ExpensifyNewKansas-MediumItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = D2AFB39EC1D44BF9B91D3227 /* ExpensifyNewKansas-MediumItalic.otf */; };
 		D27CE6B77196EF3EF450EEAC /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 0D3F9E814828D91464DF9D35 /* PrivacyInfo.xcprivacy */; };
@@ -141,6 +142,7 @@
 		8B28D84EF339436DBD42A203 /* ExpensifyNeue-BoldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-BoldItalic.otf"; path = "../assets/fonts/native/ExpensifyNeue-BoldItalic.otf"; sourceTree = "<group>"; };
 		8EFE0319D586C1078DB926FD /* Pods-NewExpensify.releaseadhoc.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.releaseadhoc.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.releaseadhoc.xcconfig"; sourceTree = "<group>"; };
 		9196A72C11B91A52A43D6E8A /* libPods-NotificationServiceExtension.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NotificationServiceExtension.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		AC131FBA2CF634F20010CE80 /* BackgroundTasks.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = BackgroundTasks.framework; path = System/Library/Frameworks/BackgroundTasks.framework; sourceTree = SDKROOT; };
 		BBE493797E97F2995E627244 /* Pods-NotificationServiceExtension.debugadhoc.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationServiceExtension.debugadhoc.xcconfig"; path = "Target Support Files/Pods-NotificationServiceExtension/Pods-NotificationServiceExtension.debugadhoc.xcconfig"; sourceTree = "<group>"; };
 		BCD444BEDDB0AF1745B39049 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-NewExpensify-NewExpensifyTests/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
 		BF6A4C5167244B9FB8E4D4E3 /* ExpensifyNeue-Italic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-Italic.otf"; path = "../assets/fonts/native/ExpensifyNeue-Italic.otf"; sourceTree = "<group>"; };
@@ -180,6 +182,7 @@
 				383643682B6D4AE2005BB9AE /* DeviceCheck.framework in Frameworks */,
 				E51DC681C7DEE40AEBDDFBFE /* BuildFile in Frameworks */,
 				E51DC681C7DEE40AEBDDFBFE /* BuildFile in Frameworks */,
+				AC131FBB2CF634F20010CE80 /* BackgroundTasks.framework in Frameworks */,
 				8744C5400E24E379441C04A4 /* libPods-NewExpensify.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -239,6 +242,7 @@
 		2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
+				AC131FBA2CF634F20010CE80 /* BackgroundTasks.framework */,
 				383643672B6D4AE2005BB9AE /* DeviceCheck.framework */,
 				ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
 				ED2971642150620600B7C4FE /* JavaScriptCore.framework */,
diff --git a/ios/NewExpensify/AppDelegate.mm b/ios/NewExpensify/AppDelegate.mm
index 5608c44823f4..5d419f5a623e 100644
--- a/ios/NewExpensify/AppDelegate.mm
+++ b/ios/NewExpensify/AppDelegate.mm
@@ -9,6 +9,8 @@
 #import "RCTBootSplash.h"
 #import "RCTStartupTimer.h"
 #import <HardwareShortcuts.h>
+#import <BackgroundTasks/BackgroundTasks.h>
+#import <expensify-react-native-background-task/RNBackgroundTaskManager.h>
 
 @interface AppDelegate () <UNUserNotificationCenterDelegate>
 
@@ -49,6 +51,8 @@ - (BOOL)application:(UIApplication *)application
       [UIApplication sharedApplication].applicationIconBadgeNumber = 0;
       [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"isFirstRunComplete"];
   }
+  
+  [RNBackgroundTaskManager setup];
 
   return YES;
 }
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index 8fc94ef68584..e2308df8eb6d 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -2,6 +2,10 @@
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
+	<key>BGTaskSchedulerPermittedIdentifiers</key>
+	<array>
+		<string>com.chat.expensify.backgroundTaskSync</string>
+	</array>
 	<key>CADisableMinimumFrameDurationOnPhone</key>
 	<true/>
 	<key>CFBundleDevelopmentRegion</key>
@@ -97,6 +101,8 @@
 	<key>UIBackgroundModes</key>
 	<array>
 		<string>remote-notification</string>
+		<string>fetch</string>
+		<string>processing</string>
 	</array>
 	<key>UIFileSharingEnabled</key>
 	<true/>
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 58bae61afde8..4ddb40b55336 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -35,6 +35,27 @@ PODS:
   - EXImageLoader (5.0.0):
     - ExpoModulesCore
     - React-Core
+  - expensify-react-native-background-task (0.0.0):
+    - DoubleConversion
+    - glog
+    - hermes-engine
+    - RCT-Folly (= 2024.01.01.00)
+    - RCTRequired
+    - RCTTypeSafety
+    - React-Core
+    - React-debug
+    - React-Fabric
+    - React-featureflags
+    - React-graphics
+    - React-ImageManager
+    - React-NativeModulesApple
+    - React-RCTFabric
+    - React-rendererdebug
+    - React-utils
+    - ReactCodegen
+    - ReactCommon/turbomodule/bridging
+    - ReactCommon/turbomodule/core
+    - Yoga
   - Expo (52.0.14):
     - ExpoModulesCore
   - ExpoAsset (11.0.1):
@@ -2813,6 +2834,7 @@ DEPENDENCIES:
   - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
   - EXAV (from `../node_modules/expo-av/ios`)
   - EXImageLoader (from `../node_modules/expo-image-loader/ios`)
+  - "expensify-react-native-background-task (from `../node_modules/@expensify/react-native-background-task`)"
   - Expo (from `../node_modules/expo`)
   - ExpoAsset (from `../node_modules/expo-asset/ios`)
   - ExpoFont (from `../node_modules/expo-font/ios`)
@@ -2982,6 +3004,8 @@ EXTERNAL SOURCES:
     :path: "../node_modules/expo-av/ios"
   EXImageLoader:
     :path: "../node_modules/expo-image-loader/ios"
+  expensify-react-native-background-task:
+    :path: "../node_modules/@expensify/react-native-background-task"
   Expo:
     :path: "../node_modules/expo"
   ExpoAsset:
@@ -3228,6 +3252,7 @@ SPEC CHECKSUMS:
   DoubleConversion: f16ae600a246532c4020132d54af21d0ddb2a385
   EXAV: 9773c9799767c9925547b05e41a26a0240bb8ef2
   EXImageLoader: 759063a65ab016b836f73972d3bb25404888713d
+  expensify-react-native-background-task: 6f797cf470b627912c246514b1631a205794775d
   Expo: 0e7b52be71a24a38d5e919e3040d8f51a8739cd0
   ExpoAsset: 8138f2a9ec55ae1ad7c3871448379f7d97692d15
   ExpoFont: 7522d869d84ee2ee8093ee997fef5b86f85d856b
diff --git a/ios/tmp.xcconfig b/ios/tmp.xcconfig
new file mode 100644
index 000000000000..ee98b7b0bd8c
--- /dev/null
+++ b/ios/tmp.xcconfig
@@ -0,0 +1,12 @@
+NEW_EXPENSIFY_URL=https:/$()/new.expensify.com/
+SECURE_EXPENSIFY_URL=https:/$()/secure.expensify.com/
+EXPENSIFY_URL=https:/$()/www.expensify.com/
+EXPENSIFY_PARTNER_NAME=chat-expensify-com
+EXPENSIFY_PARTNER_PASSWORD=e21965746fd75f82bb66
+PUSHER_APP_KEY=268df511a204fbb60884
+USE_WEB_PROXY=false
+ENVIRONMENT=production
+SEND_CRASH_REPORTS=true
+FB_API_KEY=AIzaSyBrLKgCuo6Vem6Xi5RPokdumssW8HaWBow
+FB_APP_ID=1:1008697809946:web:08de4ecb7656b7235445a3
+FB_PROJECT_ID=expensify-mobile-app
diff --git a/jest/setup.ts b/jest/setup.ts
index c575054f7dac..4db3d945ad8f 100644
--- a/jest/setup.ts
+++ b/jest/setup.ts
@@ -83,6 +83,11 @@ jest.mock('@src/libs/actions/Timing', () => ({
     end: jest.fn(),
 }));
 
+jest.mock('../modules/background-task/src/NativeReactNativeBackgroundTask', () => ({
+    defineTask: jest.fn(),
+    onBackgroundTaskExecution: jest.fn(),
+}));
+
 // This makes FlatList render synchronously for easier testing.
 jest.mock(
     '@react-native/virtualized-lists/Interaction/Batchinator',
diff --git a/modules/background-task/expensify-react-native-background-task.podspec b/modules/background-task/expensify-react-native-background-task.podspec
new file mode 100644
index 000000000000..207cd239c463
--- /dev/null
+++ b/modules/background-task/expensify-react-native-background-task.podspec
@@ -0,0 +1,20 @@
+require "json"
+
+package = JSON.parse(File.read(File.join(__dir__, "package.json")))
+folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
+
+Pod::Spec.new do |s|
+  s.name         = "expensify-react-native-background-task"
+  s.version      = package["version"]
+  s.summary      = package["description"]
+  s.homepage     = package["homepage"]
+  s.license      = package["license"]
+  s.authors      = package["author"]
+
+  s.platforms    = { :ios => min_ios_version_supported }
+  s.source       = { :git => ".git", :tag => "#{s.version}" }
+
+  s.source_files = "ios/**/*.{h,m,mm,cpp}"
+
+  install_modules_dependencies(s)
+end
diff --git a/modules/background-task/ios/RNBackgroundTaskManager.h b/modules/background-task/ios/RNBackgroundTaskManager.h
new file mode 100644
index 000000000000..38a8a88e734d
--- /dev/null
+++ b/modules/background-task/ios/RNBackgroundTaskManager.h
@@ -0,0 +1,15 @@
+#import <Foundation/Foundation.h>
+#import <BackgroundTasks/BackgroundTasks.h>
+#import <React/RCTBridgeModule.h>
+
+@interface RNBackgroundTaskManager : NSObject
+
+@property (nonatomic, copy) void (^ _Nullable taskHandler)(BGTask * _Nonnull);
+
++ (instancetype _Nullable )shared;
++ (void)setup;
+- (void)setHandlerForIdentifier:(NSString *_Nullable)identifier
+                     completion:(void (^_Nullable)(BGTask * _Nonnull))handler;
+- (void (^_Nullable)(BGTask * _Nonnull))handlerForIdentifier:(NSString *_Nullable)identifier;
+
+@end
diff --git a/modules/background-task/ios/RNBackgroundTaskManager.m b/modules/background-task/ios/RNBackgroundTaskManager.m
new file mode 100644
index 000000000000..f0bc85dfaa9f
--- /dev/null
+++ b/modules/background-task/ios/RNBackgroundTaskManager.m
@@ -0,0 +1,52 @@
+#import <BackgroundTasks/BackgroundTasks.h>
+
+@implementation RNBackgroundTaskManager : NSObject  {
+    NSMutableDictionary<NSString *, void (^)(BGTask * _Nonnull)> *_handlers;
+}
+
++ (instancetype)shared {
+    static RNBackgroundTaskManager *instance = nil;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        instance = [[RNBackgroundTaskManager alloc] init];
+    });
+    return instance;
+}
+
+- (instancetype)init {
+    if (self = [super init]) {
+        _handlers = [NSMutableDictionary new];
+    }
+    return self;
+}
+
+- (void)setHandlerForIdentifier:(NSString *)identifier
+                    completion:(void (^)(BGTask * _Nonnull))handler {
+    _handlers[identifier] = handler;
+}
+
+- (void (^)(BGTask * _Nonnull))handlerForIdentifier:(NSString *)identifier {
+    return _handlers[identifier];
+}
+
++ (void)setup {
+    NSArray *backgroundIdentifiers = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"BGTaskSchedulerPermittedIdentifiers"];
+
+    if (!backgroundIdentifiers || ![backgroundIdentifiers isKindOfClass:[NSArray class]]) {
+        NSLog(@"[ReactNativeBackgroundTask] No background identifiers found or invalid format");
+    } else {
+      for (NSString *identifier in backgroundIdentifiers) {
+          [[BGTaskScheduler sharedScheduler] registerForTaskWithIdentifier:identifier
+                                                              usingQueue:nil
+                                                           launchHandler:^(BGTask * _Nonnull task) {
+              NSLog(@"[ReactNativeBackgroundTask] Executing background task: %@", task.identifier);
+              void (^handler)(BGTask * _Nonnull) = [[RNBackgroundTaskManager shared] handlerForIdentifier:task.identifier];
+              if (handler) {
+                  handler(task);
+              }
+          }];
+      }
+    }
+}
+
+@end
diff --git a/modules/background-task/ios/ReactNativeBackgroundTask.h b/modules/background-task/ios/ReactNativeBackgroundTask.h
new file mode 100644
index 000000000000..93d1e83a6878
--- /dev/null
+++ b/modules/background-task/ios/ReactNativeBackgroundTask.h
@@ -0,0 +1,18 @@
+#ifdef RCT_NEW_ARCH_ENABLED
+#import "RNReactNativeBackgroundTaskSpec.h"
+#import <BackgroundTasks/BackgroundTasks.h>
+
+@interface ReactNativeBackgroundTask : NativeReactNativeBackgroundTaskSpecBase <NativeReactNativeBackgroundTaskSpec>
+#else
+#import <React/RCTBridgeModule.h>
+#import <BackgroundTasks/BackgroundTasks.h>
+
+@interface ReactNativeBackgroundTask : NSObject <RCTBridgeModule>
+#endif
+
+- (void)defineTask:(NSString *)taskName
+      taskExecutor:(RCTResponseSenderBlock)taskExecutor
+          resolve:(RCTPromiseResolveBlock)resolve
+           reject:(RCTPromiseRejectBlock)reject;
+
+@end
diff --git a/modules/background-task/ios/ReactNativeBackgroundTask.mm b/modules/background-task/ios/ReactNativeBackgroundTask.mm
new file mode 100644
index 000000000000..f963c928a41e
--- /dev/null
+++ b/modules/background-task/ios/ReactNativeBackgroundTask.mm
@@ -0,0 +1,117 @@
+#import "ReactNativeBackgroundTask.h"
+#import <UIKit/UIKit.h>
+#import <BackgroundTasks/BackgroundTasks.h>
+#import "RNBackgroundTaskManager.h"
+
+@implementation ReactNativeBackgroundTask {
+    NSMutableDictionary *_taskExecutors;
+}
+
+RCT_EXPORT_MODULE()
+
+- (instancetype)init {
+    if (self = [super init]) {
+        _taskExecutors = [NSMutableDictionary new];
+    }
+    return self;
+}
+
+- (BOOL)scheduleNewBackgroundTask:(NSString *)identifier error:(NSError **)outError {
+    BGAppRefreshTaskRequest *request = [[BGAppRefreshTaskRequest alloc] initWithIdentifier:identifier];
+    
+    // Set earliest begin date to some time in the future
+    request.earliestBeginDate = [NSDate dateWithTimeIntervalSinceNow:15 * 60]; // 15 minutes from now
+    
+    NSError *error = nil;
+    BOOL success = [[BGTaskScheduler sharedScheduler] submitTaskRequest:request error:&error];
+    
+    if (!success) {
+        NSLog(@"[ReactNativeBackgroundTask] Failed to schedule task: %@", error.localizedDescription);
+        if (outError != nil) {
+            *outError = error;
+        }
+    }
+    
+    return success;
+}
+
+RCT_EXPORT_METHOD(defineTask:(NSString *)taskName
+                  taskExecutor:(RCTResponseSenderBlock)taskExecutor
+                  resolve:(RCTPromiseResolveBlock)resolve
+                  reject:(RCTPromiseRejectBlock)reject)
+{
+    if (taskName == nil) {
+        NSLog(@"[ReactNativeBackgroundTask] Failed to define task: taskName is nil");
+        reject(@"ERR_INVALID_TASK_NAME", @"Task name must be provided", nil);
+        return;
+    }
+    
+    if (taskExecutor == nil) {
+        NSLog(@"[ReactNativeBackgroundTask] Failed to define task: taskExecutor is nil");
+        reject(@"ERR_INVALID_TASK_EXECUTOR", @"Task executor must be provided", nil);
+        return;
+    }
+    
+    NSArray *backgroundIdentifiers = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"BGTaskSchedulerPermittedIdentifiers"];
+    
+    
+    if (!backgroundIdentifiers || ![backgroundIdentifiers isKindOfClass:[NSArray class]]) {
+        NSLog(@"[ReactNativeBackgroundTask] No background identifiers found or invalid format");
+        reject(@"ERR_INVALID_TASK_SCHEDULER_IDENTIFIER", @"No background identifiers found or invalid format", nil);
+        return;
+    }
+    
+    NSLog(@"[ReactNativeBackgroundTask] Defining task: %@", taskName);
+    
+    BOOL allSuccess = YES;
+    NSError *taskError = nil;
+
+    for (NSString *identifier in backgroundIdentifiers) {
+        [[RNBackgroundTaskManager shared] setHandlerForIdentifier:identifier completion:^(BGTask * _Nonnull task) {
+            NSLog(@"[ReactNativeBackgroundTask] Executing background task's handler");
+            
+            // Execute all registered tasks
+            [self->_taskExecutors enumerateKeysAndObjectsUsingBlock:^(NSString *taskName, RCTResponseSenderBlock executor, BOOL *stop) {
+                NSLog(@"[ReactNativeBackgroundTask] Executing task: %@", taskName);
+                [self emitOnBackgroundTaskExecution:(taskName)];
+            }];
+            
+            NSError *scheduleError = nil;
+            [self scheduleNewBackgroundTask:identifier error:&scheduleError];
+            
+            [task setTaskCompletedWithSuccess:YES];
+        }];
+        
+        NSError *scheduleError = nil;
+        BOOL success = [self scheduleNewBackgroundTask:identifier error:&scheduleError];
+
+        if (success) {
+            _taskExecutors[taskName] = taskExecutor;
+        } else {
+            allSuccess = NO;
+            taskError = scheduleError;
+            break;  
+        }
+    }
+
+    if (allSuccess) {
+        resolve(@YES);
+    } else {
+        reject(@"ERR_SCHEDULE_TASK_FAILED", 
+               taskError.localizedDescription ?: @"Failed to schedule initial background task",
+               taskError);
+    }
+
+    _taskExecutors[taskName] = taskExecutor;
+}
+
+// Don't compile this code when we build for the old architecture.
+#ifdef RCT_NEW_ARCH_ENABLED
+- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
+    (const facebook::react::ObjCTurboModule::InitParams &)params
+{
+    return std::make_shared<facebook::react::NativeReactNativeBackgroundTaskSpecJSI>(params);
+}
+#endif
+
+@end
diff --git a/modules/background-task/package.json b/modules/background-task/package.json
new file mode 100644
index 000000000000..92d464777bae
--- /dev/null
+++ b/modules/background-task/package.json
@@ -0,0 +1,19 @@
+{
+  "name": "@expensify/react-native-background-task",
+  "version": "0.0.0",
+  "description": "Execute tasks in background",
+  "main": "src/index",
+  "codegenConfig": {
+    "name": "RNReactNativeBackgroundTaskSpec",
+    "type": "modules",
+    "jsSrcsDir": "src"
+  },
+  "author": " <> ()",
+  "license": "UNLICENSED",
+  "homepage": "#readme",
+  "create-react-native-library": {
+    "type": "module-mixed",
+    "languages": "kotlin-objc",
+    "version": "0.44.1"
+  }
+}
diff --git a/modules/background-task/react-native.config.js b/modules/background-task/react-native.config.js
new file mode 100644
index 000000000000..d532440e69b0
--- /dev/null
+++ b/modules/background-task/react-native.config.js
@@ -0,0 +1,10 @@
+/**
+ * @type {import('@react-native-community/cli-types').UserDependencyConfig}
+ */
+module.exports = {
+    dependency: {
+        platforms: {
+            android: null,
+        },
+    },
+};
diff --git a/modules/background-task/src/NativeReactNativeBackgroundTask.ts b/modules/background-task/src/NativeReactNativeBackgroundTask.ts
new file mode 100644
index 000000000000..792fe2850552
--- /dev/null
+++ b/modules/background-task/src/NativeReactNativeBackgroundTask.ts
@@ -0,0 +1,12 @@
+import type {TurboModule} from 'react-native';
+import {TurboModuleRegistry} from 'react-native';
+import type {EventEmitter} from 'react-native/Libraries/Types/CodegenTypes';
+
+// We need to export the interface inline for proper TypeScript type inference with TurboModules
+// eslint-disable-next-line rulesdir/no-inline-named-export, @typescript-eslint/consistent-type-definitions
+export interface Spec extends TurboModule {
+    defineTask(taskName: string, taskExecutor: (data: unknown) => void | Promise<void>): Promise<void>;
+    readonly onBackgroundTaskExecution: EventEmitter<string>;
+}
+
+export default TurboModuleRegistry.getEnforcing<Spec>('ReactNativeBackgroundTask');
diff --git a/modules/background-task/src/index.ts b/modules/background-task/src/index.ts
new file mode 100644
index 000000000000..d3afe75a85bc
--- /dev/null
+++ b/modules/background-task/src/index.ts
@@ -0,0 +1,35 @@
+import NativeReactNativeBackgroundTask from './NativeReactNativeBackgroundTask';
+
+type TaskManagerTaskExecutor<T = unknown> = (data: T) => void | Promise<void>;
+
+const taskExecutors = new Map<string, TaskManagerTaskExecutor>();
+
+NativeReactNativeBackgroundTask.onBackgroundTaskExecution((taskName) => {
+    const executor = taskExecutors.get(taskName);
+
+    if (executor) {
+        executor(taskName);
+    }
+});
+
+const TaskManager = {
+    /**
+     * Defines a task that can be executed in the background.
+     * @param taskName - Name of the task. Must be unique and match the name used when registering the task.
+     * @param taskExecutor - Function that will be executed when the task runs.
+     */
+    defineTask: (taskName: string, taskExecutor: TaskManagerTaskExecutor): Promise<void> => {
+        if (typeof taskName !== 'string' || taskName.length === 0) {
+            throw new Error('Task name must be a string');
+        }
+        if (typeof taskExecutor !== 'function') {
+            throw new Error('Task executor must be a function');
+        }
+
+        taskExecutors.set(taskName, taskExecutor);
+
+        return NativeReactNativeBackgroundTask.defineTask(taskName, taskExecutor);
+    },
+};
+
+export default TaskManager;
diff --git a/package-lock.json b/package-lock.json
index d19fa45d10d9..d058b70a832c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,7 @@
       "license": "MIT",
       "dependencies": {
         "@dotlottie/react-player": "^1.6.3",
+        "@expensify/react-native-background-task": "file:./modules/background-task",
         "@expensify/react-native-live-markdown": "0.1.210",
         "@expo/metro-runtime": "^4.0.0",
         "@firebase/app": "^0.10.10",
@@ -285,6 +286,11 @@
         "npm": "10.8.2"
       }
     },
+    "modules/background-task": {
+      "name": "@expensify/react-native-background-task",
+      "version": "0.0.0",
+      "license": "UNLICENSED"
+    },
     "node_modules/@0no-co/graphql.web": {
       "version": "1.0.11",
       "resolved": "https://registry.npmjs.org/@0no-co/graphql.web/-/graphql.web-1.0.11.tgz",
@@ -3630,6 +3636,10 @@
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
       }
     },
+    "node_modules/@expensify/react-native-background-task": {
+      "resolved": "modules/background-task",
+      "link": true
+    },
     "node_modules/@expensify/react-native-live-markdown": {
       "version": "0.1.210",
       "resolved": "https://registry.npmjs.org/@expensify/react-native-live-markdown/-/react-native-live-markdown-0.1.210.tgz",
diff --git a/package.json b/package.json
index 0a12899cccd5..4ac373b95aca 100644
--- a/package.json
+++ b/package.json
@@ -77,6 +77,7 @@
   "dependencies": {
     "@dotlottie/react-player": "^1.6.3",
     "@expensify/react-native-live-markdown": "0.1.210",
+    "@expensify/react-native-background-task": "file:./modules/background-task",
     "@expo/metro-runtime": "^4.0.0",
     "@firebase/app": "^0.10.10",
     "@firebase/performance": "^0.6.8",
diff --git a/src/App.tsx b/src/App.tsx
index e11592609350..420901e4999e 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -40,6 +40,7 @@ import {ReportIDsContextProvider} from './hooks/useReportIDs';
 import OnyxUpdateManager from './libs/actions/OnyxUpdateManager';
 import {ReportAttachmentsProvider} from './pages/home/report/ReportAttachmentsContext';
 import type {Route} from './ROUTES';
+import './setup/backgroundTask';
 import {SplashScreenStateContextProvider} from './SplashScreenStateContext';
 
 type AppProps = {
diff --git a/src/setup/backgroundTask/index.ios.ts b/src/setup/backgroundTask/index.ios.ts
new file mode 100644
index 000000000000..e616dbb2dcb8
--- /dev/null
+++ b/src/setup/backgroundTask/index.ios.ts
@@ -0,0 +1,10 @@
+import TaskManager from '@expensify/react-native-background-task';
+import Log from '@libs/Log';
+import {flush} from '@libs/Network/SequentialQueue';
+
+const BACKGROUND_FETCH_TASK = 'FLUSH-SEQUENTIAL-QUEUE-BACKGROUND-FETCH';
+
+TaskManager.defineTask(BACKGROUND_FETCH_TASK, () => {
+    Log.info('BackgroundTask', true, `Executing ${BACKGROUND_FETCH_TASK} background task at ${new Date().toISOString()}`);
+    flush();
+});
diff --git a/src/setup/backgroundTask/index.ts b/src/setup/backgroundTask/index.ts
new file mode 100644
index 000000000000..e69de29bb2d1
