Free tool

Version / build number helper.

Pick the next CFBundleShortVersionString and CFBundleVersion for your App Store Connect upload. Validates Apple's length and format rules, warns if you skip numbers against your last 5 releases, and gives you the exact strings to paste into Info.plist or set via agvtool.

Paste into Info.plist

// Enter current version + build, then click a bump button

Marketing version vs build number

iOS ships two version identifiers in every binary, and both appear in App Store Connect:

  • CFBundleShortVersionString — shown in App Store Connect as Version. This is the marketing version users see in the App Store and under Settings → General → iPhone Storage. Apple's rule: numeric major.minor[.patch] with up to three dot-separated integers, max 18 characters total. Valid: 1, 1.0, 1.2.3. Invalid: 1.0.0-beta, 2.0-rc1, 1.2.3.4.
  • CFBundleVersion — shown as Build. Apple's rule: numeric, usually a single integer or two-part integer.integer. Must be unique per CFBundleShortVersionString. Once you upload Version 1.2.0 / Build 42, you cannot upload another binary with the same combination — even if you deleted the first.

Common workflows

Teams generally pick one of three patterns for build numbering:

  • Monotonic across versions. Build only ever increases. After uploading 1.2.0 / 42, the next upload (even for 1.2.1) is build 43. The simplest rule and what most CI systems default to. Set CURRENT_PROJECT_VERSION to a monotonic counter.
  • Reset per version. 1.2.0 / 1, 1.2.0 / 2, new marketing version resets to 1. More human-readable in TestFlight but requires more discipline — you can still re-use build 1 for 1.2.1 since it belongs to a different version.
  • Timestamp build. CFBundleVersion set to YYYYMMDDHHMM or seconds since epoch. Impossible to collide, impossible to reason about at a glance.

What App Store Connect actually enforces at upload

When you upload a binary through Xcode or xcrun altool / xcrun notarytool, Apple's iTunes Connect service runs these checks:

  • CFBundleShortVersionString matches the numeric pattern (up to 3 groups, total 18 chars).
  • CFBundleVersion is present and non-empty.
  • The combination (app ID, short version, build) is unique — this is the check that kicks back "ERROR ITMS-90062: This bundle is invalid. The value for key CFBundleVersion must be a higher number than the previously uploaded version."
  • The short version is not lower than the highest released version for a new "Ready for Sale" submission — you cannot go 1.3.0 back to 1.2.5 for a new release.

SemVer vs Apple's loose interpretation

Apple does not enforce SemVer semantics. The rule is just "up to three numeric groups, up to 18 characters." You can ship 1 → 2 → 3 with no dots, or jump from 1.0.0 to 5.2.1 without shipping anything in between. Apple will warn on the App Store Connect web UI if your increment looks abnormal — for instance going backwards — but the ITC check is what actually blocks.

Tip: AppConsul reads the current version from App Store Connect before you create a new version, so you see the authoritative "latest" value and never accidentally upload a lower short version than what is already live. See AppConsul →

Hot patches and why they're restricted

Apple guideline 3.3.2 restricts how apps can change executable behavior after review. Content updates (adding JSON configuration, remote text, remote assets) are allowed. Replacing executable code via a downloaded payload is not — and has been the subject of enforcement actions against apps using JSPatch, Rollout, and similar frameworks.

The practical implication: every meaningful change that reaches an end user on the App Store needs to go through a reviewed version. TestFlight builds reach testers quickly (often under a day for automatic review of minor internal builds, up to two days for external TestFlight submissions), but App Store production users require a full review.

Frequently asked questions

What is the difference between version and build number on iOS?

CFBundleShortVersionString is the marketing version (shown to users). CFBundleVersion is the internal build, must be unique per marketing version.

Can I reuse a build number?

Only across different CFBundleShortVersionString values. Within the same marketing version, every build number must be unique.

Do I have to increment build for every TestFlight upload?

Yes. Every upload needs a unique CFBundleVersion within its short version. Most teams auto-increment via a build-phase script or CI step.

Can I ship hot patches without a new App Store version?

Content updates yes, executable code no. Guideline 3.3.2 prohibits replacing runtime logic via downloaded code.

Managing versions across many apps? Use AppConsul.

AppConsul reads the current App Store Connect version state per app, flags collisions before upload, and can create new versions through the API.

See AppConsul →