Performance Degradation on Android after New Architecture Migration
Description
After upgrading React Native to the New Architecture, react-native-reanimated causes severe performance issues on Android. Animations that previously ran smoothly now stutter and lag heavily, making the app nearly unusable.
I tested Reanimated versions from 3.16.0 to 4.0.0, and none of them resolved the issue. Performance is excellent on the Old Architecture, but significantly degraded with the New Architecture — only on Android.
Steps to reproduce
Steps to reproduce the behavior:
- Setup a React Native project with New Architecture enabled.
- Add a simple screen with Reanimated-based animations (nerly all type of animation will cause that).
- Add a
PressableorTouchableelement that triggers animation. (prefered if this elements are also animated) - Run the app on Android, you will notice severe animation lag or stuttering.
- Run the same app on Old Architecture — animations are smooth.
- Run the same app on iOS — animations are smooth.
Screenshots or video
Can provide video comparison if needed (Old Arch vs. New Arch on Android).
Many libraries we rely on require the New Architecture, and all work great except Reanimated.
This issue is blocking our production work. We’ve confirmed it’s not our app logic — the problem occurs on minimal examples too. It’s easily reproducible.
This bug is affecting multiple teams and developers. There are many reports and mentions of degraded Reanimated performance on Android after enabling the New Architecture.
- Is this a known issue?
- Are there any workarounds or optimizations we can try?
- Is a fix in progress?
🙏 Thank you!
We appreciate the amazing work the Reanimated team does and hope this can be resolved soon. Please let us know how we can help in debugging or testing.
Snack or a link to a repository
https://snack.expo.dev/@abdelalim_chicha/19f04f
Reanimated version
3.17.4
React Native version
0.78
Platforms
Android
JavaScript runtime
Hermes
Workflow
Expo Dev Client
Architecture
Fabric (New Architecture)
Build type
Debug app & dev bundle
Device
Real device
Host machine
Linux
Device model
Galaxy s9 with android 10
Acknowledgements
Yes
i did upload all the code but from the snack file u could understand type aniamtions there, just simple once on a sign up screen makes the app unsabe, again thank for your help : )
Hello any updates,
i did upload all the code but from the snack file u could understand type aniamtions there, just simple once on a sign up screen makes the app unsabe, again thank for your help : )
I have run the repro you have provided but haven't noticed any performance regressions.
Can you tell us more specifically what is the problem? I'm afraid "performance degradation" is too broad for us to investigate. We need to know exactly how to reproduce the problem if you want us to fix it.
Thanks for getting back to me.
I understand the need for a detailed reproduction, and I will create one as soon as I have the time. I plan to provide two versions—one using the old architecture and one using the new architecture—to clearly show the differences. Unfortunately, I'm currently very busy and can’t put that together right away.
That said, I want to emphasize that this issue seems to be directly related to the upgrade. While there isn’t a single specific case to isolate it, the problem becomes very noticeable when there are more than 3–4 animations running simultaneously. In such scenarios, the performance drops significantly, but only on Android—iOS remains smooth.
As a general suggestion, if you take any existing app that includes animations and build it with the new architecture enabled, you should be able to spot the degradation compared to the same app running on the old architecture.
I’ve also seen several other developers mention the same issue on Twitter, so it doesn’t seem to be isolated to my project.
Thanks again, and I’ll follow up with the detailed reproduction as soon as possible.
Also i have check #7464 and i seems related, bu the problem is not related to sdk 53, it is from the first time reanimated adapted the new arch.
Please check #6559 , you could see in the videos what I mean.
I mean this one too #6710
Also related #7460
Hello any updates !? , at least tell us if u guys are working on this, this very very critical; (
any updates I am having significant issues on IOS!!
I have bought and iPhone and a MacBook in order to finish my work, for now iOS version works great, 3.18.0 , v4 beta 3 is totally broken , so if your are using it just downgrade and everything should work fine enough
I've used 3.17 and 4.0.1 with bare react native project, just plain translateX animation not runs at 120 FPS on Pro Motion screen on IOS. It's a disaster, I'm not expecting 120 FPS on heavy animated or complex screens, but for plain simple animations at my point of view it must be 120 FPS
@Navipro70 Can you send us a repro? Do you use useAnimatedScrollHandler? Are there React commits happening during the animation? How exactly do you measure UI FPS so you know it's not 120 fps?
@tomekzaw Hello, thank you very much for a fast reply!
I was working hard to make a reproducible repo, now I have it at my personal application. I've created a sample native module with Fabric View which just present a simple animation thought UIView to compare similar behavior with reanimated and animated (e.g. modal like animation), so I got the next benchmark results (by my eyes only, unfortunately):
- Native View 120 FPS
- Animated ~60 FPS
- Reanimated ~30-60 FPS
Those values are being provided from my point of view at release scheme builded on a physical device, without tool to measure, because I don't know how to measure it and what tool should I use, I don't know how to measure 120 FPS in react-native IOS device (perf monitor is 60 FPS, flashlight is android only), but moreover it seems that fps is dropping for exact animation and component, because I've found this reanimated lagging behavior on my animated header with scroll and when I was releasing the finger to start header animation I saw both scroll and header translations, and scroll was smooth like 120 FPS, when the header transition was worser (30-60 FPS).
I also tested release scheme build on a simulator and didn't saw any performance issues, all examples were working at 120 FPS (also my eyes benchmark 😅). To my defence, I'd want to say that every friend of mine who tested my application said that animations aren't smooth enough.
Answering your questions:
- Tried
useAnimatedScrollHandler,onScrollby itself andonScrolllike a'worklet'- met the same behavior - Checked
Profilerfor a scroll example, there were just <0.1ms renderers without components rerenders - Already said a lot about measuring, unfortunately it's my and my friends point of view cuz I don't know a tool for measuring and I'm assuming that it will not help us, because problem is related only to reanimated part and don't impact the Phone FPS
Tomorrow will drop a repo with source code, need some time to bring the files and asure the consistency of reproduction
I've found this reanimated lagging behavior on my animated header with scroll and when I was releasing the finger to start header animation I saw both scroll and header translations, and scroll was smooth like 120 FPS, when the header transition was worser (30-60 FPS).
Does it look somewhat similar to this video recording (i.e. animated header is out sync with scroll offset)?
https://github.com/user-attachments/assets/896ff146-9297-492e-90f6-06c5dcb68ae0
@tomekzaw no, it doesn't related to a sticky header, scroll position and etc. I show and hide my header after 200 px scrolling from top of a screen, by signle call withTiming to translateX header and show to user
@tomekzaw Also experiencing performance degradation over here that seems to be related to ScrollViews and the amount of Reanimated components that are rendered at a given point in time.
To preface, I am not using useAnimatedScrollHandler and there are no React commits happening when the lag occurs. In my case, there is heavy stuttering when panning any ScrollView while there is a significant amount of Reanimated components rendered outside of the ScrollView itself (completely different component, not a sibling of the ScrollView). Other parts of the app, including animations, are not affected regardless of how many Reanimated components are mounted on the DOM.
Once I reduce the amount of Reanimated components being rendered, the ScrollView stuttering does not occur anymore. This only happens on the New Architecture, tested on Reanimated v4.
The original issue is related only for Android, so I've created another one with highly described reproducible steps and repository example.
@mimo-10 Did you tested performance on a Pro Motion screen in released application? I think you should run into the same behavior as me for Pro Motion devices
No, I haven’t tested it on a ProMotion screen. I tested it on an iPhone 13. The production app performs reasonably well — although it doesn’t consistently reach 60 FPS on many screens, it’s acceptable for now. On Android, the performance is slightly worse. For example, on a Galaxy S9, the production version struggles more and fails to reach 60 FPS on more screens.
I also tested it on a OnePlus 11R. It can reach 120 FPS when no animations are running, but as soon as any animation is triggered, performance drops significantly — sometimes barely hitting 30 FPS. The issue doesn’t seem to be related to scroll handlers specifically (though adding them does make performance even worse). Instead, the problem appears to be with running multiple animations simultaneously. When only one or two animations are active, everything runs smoothly. But with more than that, performance becomes very unstable — especially during development. Again, I recommend reviewing the changes introduced between version 3.15 and 3.16. The shift to the new architecture seems to be the cause, since the older architecture worked perfectly fine. I would like also to highlight that sometimes fps gets as low as 1 to 3 fps.
No, I haven’t tested it on a ProMotion screen. I tested it on an iPhone 13. The production app performs reasonably well — although it doesn’t consistently reach 60 FPS on many screens, it’s acceptable for now
I do think we have similar problems, I don't run android cuz no need it for now. On an iPhone with Pro Motion you should meet the same behavior as me (60 FPS or even lower). I've changed FPS to 60 on my iPhone and tested the UI - all looks normal (laggy for me after 120 😅), but native animations and reanimated animations are exactly the same, however reanimated sometimes was dropping lower then 60 FPS for very simple behavior like a "open modal by pressing the button" on a Pro Motion if you run animation like 5-20 times, it starts performing 30 FPS (from my view)
@tomekzaw maybe this info also will help
I’ll be sharing some videos soon to show how the app performs — particularly on the iPhone 13. iOS handles things quite well, but on Android, the performance is significantly worse to the point of being almost unusable.
To demonstrate that the issue is specifically caused by Reanimated (and not React itself, the new architecture, or any related library), I created two nearly identical components. Both are simple and use just a couple of SharedValues — one uses the standard Animated API, and the other uses Reanimated.
Both components were tested in the same environment. The version using the Animated API has virtually no impact on FPS, which makes sense given the simplicity of the animation and the capability of the device.
However, the Reanimated version clearly causes a noticeable frame drop — sometimes as much as 15 FPS, down to around 45 FPS. Interestingly, the drop isn’t immediate; it still even after the animation finished. This means that if any additional animations are triggered afterward, performance degrades even further.
https://github.com/user-attachments/assets/44735ed2-e0a2-43db-b0d1-38b0081c447d
**side-note : usenativedriver is set to true , also "add poll" animated api , "add quiz" reanimated. **
Moving on, this next video demonstrates how useScrollHandler behaves unstably — even on iOS. The performance degradation occurs only when animations are running. At times, the frame rate drops as low as 4 FPS. While some slowdown is acceptable, having animations completely freeze like this should never happen.
It’s worth mentioning that this scroll behavior works fine in the iOS production build. However, horizontal scroll performance is noticeably worse — even in the production version — and doesn’t perform as well as expected.
I also tested the exact same screens using animations created with the Animated API, and the performance was excellent — even in the development build. Additionally, when there are no animations, horizontal scrolling runs at a stable 60 FPS.
https://github.com/user-attachments/assets/121851a3-046a-4d90-9d8a-65b5ea69cf2a
This strongly suggests that the degradation happens only when the horizontal scroll indicator (the purple one) is moving, which confirms that Reanimated is likely the bottleneck.
https://github.com/user-attachments/assets/8edfd703-e249-4956-be9d-d85cf292abe9
Last but not least, I created this example to demonstrate that the scroll handler itself isn’t the root issue. When there are no animated components on the screen (aside from the bottom bar), the FPS remains stable at 60 FPS on iOS.
On Android, the performance is slightly lower — around 53–55 FPS — but still within an acceptable range.
This further confirms that the performance problems arise not from useScrollHandler alone, but rather when it’s combined with Reanimated components or when multiple animations are active at the same time.
Side-note: All of these animations perform significantly better on the old architecture. In fact, in the last video, you can clearly see the animation glitching — it’s not smooth at all. Previously, I had bottom sheets with even more components (including Reanimated ones), and they ran flawlessly — even on Android — when using the old architecture. That level of performance is no longer achievable with the new setup, despite the content being simpler.
https://github.com/user-attachments/assets/bf01fdca-dd7a-437c-8a7c-67d0289faa5f
This is in the same app with a page that does not have more than 2 animated component( it barely degrades)
https://github.com/user-attachments/assets/2373b483-d165-42ab-a96d-359494e1ce2d
Sorry forget to embed this for scroll behavior
https://github.com/user-attachments/assets/12e220e8-3ccb-4767-8d41-47bf581496c0
What a mess!
I've found that I didn't set flag at my Info.plist CADisableMinimumFrameDurationOnPhone to true (I didn't have it at all)
After adding this flag all animations become smooth! So my personal IOS issue wasn't related to a performance degradation, I think I've missed the documentation or CADisableMinimumFrameDurationOnPhone was missed at all.
@tomekzaw news ?!
@mimo-10 What kind of news do you expect? I've already tested out the repro you have provided in the issue description and I couldn't reproduce the problem (https://github.com/software-mansion/react-native-reanimated/issues/7435#issuecomment-2850094218). We need to have a reproducible example that we can investigate and improve if you want us to fix it.
Thanks @tomekzaw again for your response, As I mentioned earlier https://github.com/software-mansion/react-native-reanimated/issues/7435#issuecomment-2888526212 , the performance problem isn’t tied to a specific component or isolated case. It’s a more general issue that becomes apparent when multiple animated components (typically 3–4 or more) are present on the screen—particularly on Android (especaily, but now also with ios) with the new architecture enabled. Because of this, the issue might not reproduce with a minimal example unless the example includes enough complexity to trigger the degradation (e.g., several simultaneous animations). So the problem is more about the Reanimated’s ability to handle heavier animation loads (with new arch) , rather than any one particular edge case. Again as i mentioned (beacuse any example would perform better ( 5 to 10 times) with the old arch campared to the new one, i believe that it does not need specific reproduction, any app that you have built before for example could be a test case. That said, But if a reproducible example is the best way for the team to diagnose and resolve this, I’m happy to put one together. But could you please clarify exactly what kind of details you’d like me to include in the reproduction? anything that can help ? I just want to make sure I invest the time in creating something that’s genuinely useful for your investigation. I really believe this is a critical issue, especially for apps that rely heavily on animations, and I’d love to help however I can to get it addressed.
Thanks again!, have a nice day : )
@mimo-10 From our experience, Reanimated is able to handle way way more animated components than just four, even on very low-end Android devices in debug mode, on the New Architecture.
We have a fabric-example app in our repo and it works smoothly for us both on Android and iOS.
If we are to investigate this issue, we need a way to run the app on our setup and see the regressions on our own. If you are able to put it together, we'd be genuinely happy to help you. Otherwise, we can't really do anything on our end.
If you are not able to share the code of your app publicly (e.g. your project is a commercial app) but still would like us to take a look and investigate the performance issues, please drop us a line at [email protected] and we'll see how we can work together.
@tomekzaw Could this be related to https://github.com/facebook/react-native/issues/51870?
@unendingblue Partially yes, and also to https://github.com/facebook/react-native/issues/51869
Hello,
i am experiencing also a significant performance issue after trying to upgrade to RN New Arch especially on android but also on ios. Everything works well with old arch, but not with the new one
I have build an Animated Flatlist with a complex Parallax Teaser (look in the attached video).
https://github.com/user-attachments/assets/eec86699-b240-4221-b81b-feee72c5cb54
The teaser includes 4 animations:
- translatation of image
- translation of text
- opacity of overlay mask
- stroke of masked svg image
The teaser retrieves two relevant arguments from the Flatlist:
scrollY: SharedValue<number>;
flatListLayoutInfo: SharedValue<{
height: number;
pageY: number;
} | undefined>;
In the teaser we are calculating some values:
const imageContainerViewRef = useAnimatedRef<Animated.View>();
const imageContainerLayoutInfo = useSharedValue<
{
height: number;
pageY: number;
} | undefined
>(undefined);
/*
calculate depending on flatListLayoutInfo.value and imageContainerLayoutInfo.value
*/
const animatedValues = useDerivedValue<AnimatedValues | undefined>(() => {
...
return { intersectingValue, absIntersectingValue, halfImageHeight };
});
useDerivedValue(() => {
if (imageContainerLayoutInfo.value) {
return;
}
/*
can be < 0 if pull to refresh was used
*/
if (scrollY.value <= 0) {
return;
}
const measured = measure(imageContainerViewRef);
if (!measured) {
return;
}
imageContainerLayoutInfo.value = {
height: measured.height,
pageY: measured.pageY + scrollY.value,
};
}, [scrollY.value]);
/*
animated style of dark overlay which
fades in on scroll
*/
const animatedOverlayStyle = useAnimatedStyle(() => {
...
const { intersectingValue, absIntersectingValue, halfImageHeight } =
animatedValues.value;
...
return {
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
left: 0,
backgroundColor: 'rgba(0,0,0,0.5)',
opacity: interpolate(
infosTranslateY,
[0, halfImageHeight],
[0, 0.5],
),
pointerEvents: 'none',
};
});
/*
animated style of image translation
*/
const animatedImageContainerStyle = useAnimatedStyle(() => {
...
const { intersectingValue, absIntersectingValue, halfImageHeight } =
animatedValues.value;
...
return {
transform: [
{
translateY,
},
],
};
});
/*
animated style of infos translation
*/
const animatedInfosContainerStyle = useAnimatedStyle(() => {
...
const { intersectingValue, absIntersectingValue, halfImageHeight } =
animatedValues.value;
...
return {
transform: [
{
translateY,
},
],
};
})
In the animated Image, we calculate and animate the strokeWith based in the given parameter:
animatedValues: Readonly<SharedValue<{
intersectingValue: number;
absIntersectingValue: number;
halfImageHeight: number;
} | undefined>>;
const animatedProps = useAnimatedProps(() => {
...
const { intersectingValue, absIntersectingValue, halfImageHeight } =
animatedValues.value;
// image is cutted by header
if (intersectingValue < 0) {
// image scrolled until 50% -> translate strokeWidth to make image bigger
if (absIntersectingValue <= halfImageHeight) {
return {
strokeWidth: interpolate(
absIntersectingValue,
[0, halfImageHeight],
[strokeWidthDefault, MAX_STROKE_WIDTH],
),
};
}
....
});
The animatedProps are passed into a
<AnimatedPath
...
animatedProps={animatedProps}
/>
created outside the component with
const AnimatedPath = Animated.createAnimatedComponent(Path);
THE RESULT:
On IOS, the animation is poor like in the video, but i can fix it with removing the animated Svg Path. On Android it is still poor, even if i remove the Svg Path.
Thanks for your time in advance! Greets Robert