Flutter Impeller: what the new rendering engine means for your app
By Ann Tech · 20 May 2026
Impeller is Flutter's new rendering engine, replacing Skia. It's the default on iOS since Flutter 3.10 and on Android since Flutter 3.16. If you ship Flutter apps, Impeller affects you — and mostly in a positive way.
Why Impeller was built
Skia compiled shaders at runtime — the first time a complex animation played, Skia generated the GPU shader on the fly. This caused shader compilation jank: a visible stutter the first time a transition or animation ran, impossible to reproduce in benchmarks but obvious to users.
Impeller pre-compiles a smaller, fixed set of shaders at Flutter build time. The shaders are always ready — no runtime compilation, no first-frame jank.
What Impeller changes for developers
The good
- Elimination of shader compilation jank — the biggest win. Animations are consistently smooth from the first frame.
- Better performance on metal (iOS) — Impeller uses Metal directly on iOS instead of going through the Skia-to-OpenGL abstraction layer.
- Predictable frame timing — frame budget is more consistent without random shader compilation spikes.
The tradeoffs
- Some visual differences — anti-aliasing, blur radius, and gradient rendering may look slightly different from Skia. Existing golden tests may fail.
- New bugs — Impeller is newer. Some edge cases in custom painters or advanced blend modes may render differently. Check Flutter's known issues list.
Checking if Impeller is active
import 'package:flutter/foundation.dart';
// Check renderer at runtime
final renderer = PlatformDispatcher.instance.views.first.renderingContext;
debugPrint('Renderer: $renderer'); // Prints "Impeller" or "Skia"
Or check in app settings at runtime:
flutter run --enable-impeller # Force Impeller on
flutter run --no-enable-impeller # Force Skia (for comparison)
Updating your CustomPainter for Impeller
Most CustomPainter code works unchanged. A few things to check:
// SaveLayer with complex operations — slightly different compositing in Impeller
canvas.saveLayer(bounds, Paint()..blendMode = BlendMode.multiply);
// Test this visually — behavior is correct but may look slightly different
// Blur — Impeller renders sigma slightly differently at large values
final blur = MaskFilter.blur(BlurStyle.normal, 20);
// Check golden tests for blur-heavy UIs
// Image filters — generally work, but test at edge cases
canvas.drawImage(
image,
Offset.zero,
Paint()..imageFilter = ImageFilter.blur(sigmaX: 10, sigmaY: 10),
);
Updating golden tests
Impeller produces slightly different pixel output than Skia. If your golden tests fail after upgrading Flutter, regenerate them:
flutter test --update-goldens
Commit the new goldens. If you need to support both renderers in tests, use conditional goldens:
testWidgets('button renders correctly', (tester) async {
await tester.pumpWidget(...);
await expectLater(
find.byType(AppButton),
matchesGoldenFile('goldens/button_${isImpeller ? "impeller" : "skia"}.png'),
);
});
Performance measurement with Impeller
# Profile with Impeller (default on iOS/Android now)
flutter run --profile
# Compare with Skia
flutter run --profile --no-enable-impeller
Use DevTools → Performance → Frame rendering chart. Look for consistent frame times vs spikes with Skia.
Common pitfalls
Assuming Skia and Impeller are identical. They're not pixel-perfect matches. Review UIs that use complex blend modes, large blurs, or custom compositing. Update golden tests rather than fighting the renderer.
Not testing on a physical device. Impeller performance improvements are most visible on real hardware, not simulators. The simulator uses software rendering regardless.
Filing Impeller bugs as Flutter bugs without verification. If something looks wrong, first test with --no-enable-impeller. If it looks correct with Skia, it's an Impeller issue — file it on the Flutter GitHub with both renderer screenshots.
Sign in to like, dislike, or report.