You change v1 to v2 in a Dart file. dart run prints v2, but yesterday's executable still prints v1. The saved source is correct. The executable is a separate artifact built from the earlier source.
This small experiment makes the JIT/AOT distinction concrete without reducing it to a claim that one mode is always faster.
How do dart run and dart compile exe differ?
dart run runs the program on the Dart VM. During development, the VM uses just-in-time (JIT) compilation, so a new invocation runs the current source. dart compile exe uses ahead-of-time (AOT) compilation to create a separate executable. Dart's compilation documentation distinguishes these workflows.
The key question is when the executable was built and which source it contains. Calling dart run again differs from calling an executable created yesterday. An already running dart run process does not automatically reload changed source; start it again. This is also distinct from Flutter hot reload.
Why does the existing executable still print v1?
The diagram shows two paths after the edit. A fresh dart run reads the changed source, while the old executable remains based on the original source until dart compile exe rebuilds it.
Save this as app.dart. build marks the source version, and review will be a runtime argument:
void main(List<String> args) {
const build = 'v1';
final action = args.isEmpty ? 'read' : args.first;
print('$build: $action');
}Run the source and compile an executable from it:
dart run app.dart review
# v1: review
dart compile exe app.dart -o app
./app review
# v1: reviewNow change only const build = 'v1'; in app.dart to const build = 'v2';:
dart run app.dart review
# v2: review
./app review
# v1: reviewThe executable is not broken. It still runs the program as it was compiled the first time. Editing source does not rewrite an existing binary.
How do you put the change into the executable?
Recompile it from the updated source:
dart compile exe app.dart -o app
./app review
# v2: reviewApply the same check to deployment scripts. A new source commit does not prove that the binary being deployed was rebuilt from that commit. Compare the behavior of dart run and the actual deployment artifact with the same inputs, then inspect the build step if they disagree.
The argument review is not frozen at compile time. Passing publish to the old v1 executable prints v1: publish. AOT compiles the program code ahead of time; it does not predetermine every runtime input.
Is an AOT executable always faster and portable everywhere?
An executable from compile exe includes a small Dart runtime, but it targets a particular operating system and CPU architecture. A binary built on one platform is not automatically usable on all others. Build and test for the intended target.
JIT is useful while iterating on code, and an AOT executable is useful when distributing a precompiled program. This four-line example cannot establish a universal speed ranking. Startup time, repeated execution speed, and build time are different measurements; benchmark the actual application if performance determines the choice.
Key takeaways
A new dart run invocation uses the current source. An executable made with dart compile exe reflects the source at compilation time, so you must rebuild it after editing the source. Runtime arguments can still change. When results differ, check which file was built and when.

