Fingerprint Update Strategy
Automatically prevent incompatible OTA updates by tracking native code changes with Expo's fingerprint library.
Why Choose Fingerprint?
Fingerprint automatically detects native code changes and blocks incompatible OTA updates. This ensures only safe updates reach your users.
Fingerprint vs App Version:
- Fingerprint: Automatic protection - detects native changes and blocks unsafe updates
- App Version: Manual control - you specify version targets, no automatic checking
Choose Fingerprint for automatic safety. Choose App Version for manual control.
Setup
Fingerprint is the default strategy. Configure it explicitly if needed:
import { defineConfig } from "hot-updater";
export default defineConfig({
updateStrategy: "fingerprint", // Default strategy
});Include Additional Files (Optional)
Track extra files that affect native compatibility:
import { defineConfig } from "hot-updater";
export default defineConfig({
updateStrategy: "fingerprint",
fingerprint: {
extraSources: [
"config/native-config.json",
"scripts/post-build.sh",
],
debug: true,
},
});Workflow
Before App Store Submission
Step 1: Generate Fingerprint
Before building for App Store, generate the fingerprint:
npx hot-updater fingerprint createThis creates a fingerprint.json file and embeds the hash in your native files:
- iOS:
ios/YourApp/Info.plist - Android:
android/app/src/main/res/values/strings.xml
Example fingerprint.json:
{
"ios": {
"hash": "11142b9062165fa48665f5efa095dd94e9e45eb0"
},
"android": {
"hash": "c763ed5729a0bcccf23248ee0183ddf9016c2e6e"
}
}Step 2: Build and Submit
Build your app with the embedded fingerprint and submit to the App Store.
Step 3: Deploy OTA Updates
After your app is live, deploy JavaScript-only updates:
npx hot-updater deployThe system automatically ensures only compatible updates reach users.
When Native Code Changes
Check if your fingerprint needs updating:
npx hot-updater fingerprintIf there's a mismatch, create a new fingerprint:
npx hot-updater fingerprint createImportant: After creating a new fingerprint, you must rebuild your app. The new fingerprint must be embedded in the app binary before deploying OTA updates.
Client Setup
Configure your React Native app:
import { HotUpdater, getUpdateSource } from "@hot-updater/react-native";
import { View, Text } from "react-native";
function App() {
return (
<View>
<Text>Hello World</Text>
</View>
);
}
export default HotUpdater.wrap({
source: getUpdateSource("https://your-update-server.com/api/update-check", {
updateStrategy: "fingerprint",
}),
})(App);The client automatically constructs this endpoint:
GET {baseUrl}/fingerprint/:platform/:fingerprintHash/:channel/:minBundleId/:bundleIdHow It Works
JavaScript/UI Changes ✅ OTA Update Safe
// ✅ Safe for OTA updates
// - Component logic changes
// - Style and layout updates
// - New screens
// - Business logic changes
// - API call modificationsResult: Fingerprint unchanged → OTA update deployed
Native Code Changes ⚠️ Rebuild Required
# ⚠️ Requires native rebuild
# - New native modules (react-native-camera)
# - React Native version updates
# - Native iOS/Android code changes
# - Build configuration changesResult: Fingerprint changed → OTA blocked → Rebuild needed
If you try to deploy with a changed fingerprint:
$ npx hot-updater deploy
❌ Fingerprint mismatch!
💡 Native code changed. You need to:
1. Run: npx hot-updater fingerprint create
2. Rebuild and resubmit your app
3. Then deploy OTA updatesAdvanced
Multiple App Targets
fingerprint create automatically handles standard React Native projects. Only configure custom paths if you have:
- iOS app extensions (widgets, share extensions)
- Multiple Android build variants
- Non-standard project structure
import { defineConfig } from "hot-updater";
export default defineConfig({
updateStrategy: "fingerprint",
platform: {
ios: {
infoPlistPaths: [
"ios/YourApp/Info.plist",
"ios/YourAppWidget/Info.plist",
"ios/YourAppExtension/Info.plist"
]
},
android: {
stringResourcePaths: [
"android/app/src/main/res/values/strings.xml",
"android/app/src/debug/res/values/strings.xml"
]
}
}
});💡 Most projects don't need this - the defaults work perfectly.
Testing the Endpoint
Test your update endpoint with curl:
curl "https://your-update-endpoint.com/check-update/fingerprint/ios/11142b9062165fa48665f5efa095dd94e9e45eb0/production/00000000-0000-0000-0000-000000000000/00000000-0000-0000-0000-000000000001"Parameters:
:platform-iosorandroid:fingerprintHash- Current fingerprint hash:channel- Channel name (e.g.,production,staging):minBundleId- Minimum supported bundle ID:bundleId- Current bundle ID