How to set build and version number of Flutter app
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Flutter versioning looks simple on the surface, but it still has to map into Android and iOS release rules correctly. The key is knowing which number is user-facing, which number is for store ordering, and where Flutter expects you to define them.
Use the version Field in pubspec.yaml
In a standard Flutter project, the main version definition lives in pubspec.yaml.
This format has two parts:
1.4.2is the user-facing version name.27is the build number.
The left side is what users typically see in the app store or settings screen. The right side is the monotonically increasing internal build identifier that the stores use to distinguish uploads of the same release line.
For example, if you fix a packaging issue without changing the public release version, you might keep the version name and only bump the build:
That means "same app release series, newer distributable build."
Understand How Flutter Maps to Android and iOS
Flutter translates the values into native platform settings during the build.
On Android:
- The version name maps to the visible version string.
- The build number maps to the integer code used by the platform for upgrade ordering.
On iOS:
- The version name maps to the short bundle version string.
- The build number maps to the bundle build field.
You usually do not edit those generated values manually in native files unless the project has custom native build logic. For most Flutter apps, pubspec.yaml is the single source of truth.
Override Values from the Command Line
You can also set the version name and build number at build time. This is useful when CI or release automation should stamp the artifact with pipeline-specific metadata instead of relying only on the checked-in pubspec.yaml value.
The same pattern works for other targets:
This approach is practical when the repository keeps a stable baseline version in pubspec.yaml, but the delivery pipeline needs to assign a unique build for each upload candidate.
Pick a Versioning Policy Before Releases Start
Most teams avoid confusion by choosing one policy early:
- Semantic versioning for public releases such as
2.3.1. - A strictly increasing build number for every distributable build.
That policy matters more than the exact numbering style. What breaks release pipelines is inconsistency, such as reusing build numbers or bumping one platform differently from the other.
A simple release progression might look like this:
Users see 1.0.0, 1.1.0, and 1.1.1, while the stores see a clean sequence of build identifiers.
Verify the Result in Native Projects
If the app uses custom Gradle, Xcode, flavors, or multiple targets, it is worth verifying the generated values rather than assuming they propagated correctly.
Common checks:
- Build the app.
- Open the Android or iOS output metadata.
- Confirm the visible version and build number match the intended release.
For Android projects with custom flavors, make sure version overrides do not conflict with per-flavor configuration. For iOS, ensure any manually edited native settings are not silently drifting away from the Flutter version field.
Use CI to Prevent Versioning Mistakes
Manual versioning works for small projects, but once releases become frequent, automation reduces errors. A simple CI step can reject builds where the build number did not increase or can derive it from the pipeline run number.
For example, a release job might do this:
The exact environment variable depends on your CI system, but the principle is stable: keep the public version intentional and the build number unique.
Common Pitfalls
- Changing the visible version and forgetting that store uploads still require a higher internal build number.
- Editing native Android or iOS version values manually while also relying on
pubspec.yaml, which creates drift. - Reusing a build number in CI and then being blocked by app store validation rules.
- Treating the build number as user-facing release information instead of an internal release counter.
- Starting versioning without a stable policy and then trying to clean up inconsistency after releases already exist.
Summary
- Set the main Flutter app version in
pubspec.yamlasversion_name+build_number. - The version name is user-facing, while the build number must keep increasing for release ordering.
- Flutter maps that combined value into Android and iOS native fields automatically in normal projects.
- Command-line overrides are useful for CI and release automation.
- Consistent versioning policy matters more than complicated numbering schemes.

