Which Languages Run on AWS Graviton Without Code Changes?
Migrating applications to Amazon EC2 Graviton instances is often straightforward because interpreted languages and bytecode-based runtimes abstract the underlying processor architecture from your source code. Languages such as Python, Node.js, Ruby, PHP, Java, and .NET generally require zero code modifications when transitioning from x86 to Arm64 processors, provided their third-party dependencies do not rely on architecture-specific native extensions or pre-compiled x86 binaries. Even compiled languages like Go and Rust typically only require updating the build target configuration rather than rewriting application logic.
Interpreted Languages
Interpreted and dynamically typed languages execute inside a language runtime that handles platform-specific machine instructions on behalf of your application. Because your codebase stays in plain text until the runtime interprets or just-in-time compiles it on the host machine, migrating to an Arm64 environment requires only installing the Arm64 version of the interpreter.
- Python: Pure Python applications run identically on
x86 and Arm64. Modern versions of Python (3.8 and newer) offer full
optimizations for 64-bit Arm architectures. Most popular packages
containing C or Rust extensions, such as NumPy, Pandas, and
Cryptography, publish pre-built
manylinuxaarch64 wheels to PyPI, allowingpipto install them without local compilation or code changes. - JavaScript and TypeScript (Node.js, Deno, Bun): The
V8 and JavaScriptCore engines have first-class Arm64 support. Pure
JavaScript and TypeScript applications require zero source
modifications. When using packages that rely on native addons via
node-gypor pre-built binaries, ensuring you are on current package versions guarantees that Arm64 binaries are downloaded automatically during installation. - Ruby: Standard Ruby (MRI) runs natively on Linux
Arm64 distributions. Pure Ruby scripts and frameworks like Ruby on Rails
run unmodified on Graviton. Gems with native C extensions compile
automatically during
bundle installas long as standard build tools and development headers are present on the instance. - PHP: PHP applications, including those built on Laravel, Symfony, or WordPress, execute through the Zend Engine without architecture awareness in the userland code. Installing the standard Arm64 PHP packages and extensions via your Linux distribution package manager allows existing PHP codebases to run immediately.
- Perl and Lua: Scripts written in Perl or Lua without custom inline assembly or x86-specific C bindings run directly on Arm64 interpreters without modification.
Managed Bytecode and Virtual Machine Runtimes
Languages that compile to intermediate bytecode rather than machine-specific assembly are inherently portable. The virtual machine translates the platform-neutral bytecode into native Arm64 instructions at runtime.
- Java and JVM Languages (Kotlin, Scala, Groovy,
Clojure): Java bytecode (
.classand.jarfiles) follows the write-once, run-anywhere model. You can often take the exact same.jaror.warartifact built on an x86 build server and run it directly on an Amazon Corretto or OpenJDK Arm64 runtime on Graviton. Code changes are only necessary if the application uses Java Native Interface (JNI) libraries compiled exclusively for x86 without anaarch64counterpart bundled in the archive. - .NET (C#, F#, PowerShell): Starting with .NET Core 3.1 and thoroughly matured in .NET 5, 6, 7, and 8, the .NET runtime natively supports Arm64. Framework-dependent deployments built as intermediate language (IL) assemblies require zero source code changes and run directly on the Arm64 .NET runtime, provided the application does not invoke x86-only unmanaged DLLs via P/Invoke.
- Erlang and Elixir (BEAM): Applications targeting
the BEAM virtual machine compile to portable
.beambytecode files. Standard Elixir and Erlang applications, unless utilizing custom C or Rust Native Implemented Functions (NIFs) with x86-specific instructions, transition to Graviton without code edits. - WebAssembly (Wasm): Wasm modules compiled to the WebAssembly System Interface (WASI) or executed inside runtimes like Wasmtime or WasmEdge are portable binary targets by design and run unmodified on Arm64 hosts.
Compiled Languages Requiring Only Build Flag Changes
While ahead-of-time (AOT) compiled languages produce architecture-specific binaries, modern systems languages usually require zero changes to your actual source code—only a change to your compilation environment or cross-compilation flags.
- Go: Go provides built-in cross-compilation. Unless
your codebase uses
cgowith x86-specific C libraries or platform-specific assembly files, your Go source code remains untouched. You simply compile your binary with the environment variablesGOOS=linuxandGOARCH=arm64. - Rust: Standard Rust code that avoids
architecture-specific intrinsics (such as
core::arch::x86_64) compiles directly for Graviton by targetingaarch64-unknown-linux-gnuoraarch64-unknown-linux-muslvia Cargo.
When Are Changes Actually Required?
Even when using an interpreted or bytecode language, your deployment pipeline or dependency tree might require minor adjustments in the following scenarios:
- Container Base Images: While your application code
stays the same, your
Dockerfilemust use multi-architecture base images (such aspython:3.12-slim,node:20-alpine, oramazoncorretto:21) rather than images hardcoded toamd64. - Outdated Native Dependencies: Older versions of
libraries that wrap C/C++ code might predate widespread Arm64 adoption.
Upgrading your dependency lockfiles (
package-lock.json,requirements.txt,Gemfile.lock,pom.xml) is typically sufficient to pull in pre-compiled Arm64 binaries (such as updated Netty, gRPC, or RocksDB versions in Java). - Architecture-Specific Intrinsics: Applications written in C, C++, or Rust that explicitly call x86 SIMD instructions (such as SSE or AVX) require refactoring to use portable SIMD abstractions, compiler auto-vectorization, or Arm NEON and SVE equivalents.