AWS Builder Center

“It Works on My Machine” Is a Cloud Problem Too

An application can work perfectly on a developer’s laptop and fail after deployment because of differences in configuration, dependencies, environment variables, runtime versions, or infrastructure. Learn how to make AWS deployments more predictable.

“It Works on My Machine” Is a Cloud Problem Too

Every developer has heard this sentence:
“But it works on my machine!” 😅
The application runs perfectly locally.
Then it reaches AWS.
1
2
3
4
5
6
7
Developer Laptop
↓
Works ✓

AWS
↓
Fails ❌
The code may be the same.
So what changed?

Your Application Has More Than Code

When we think about an application, we usually think:
1
2
3
Source Code
↓
Application
But the real application is closer to:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Code
+
Runtime
+
Dependencies
+
Environment Variables
+
Configuration
+
Database
+
Network
+
Permissions
Change one of these and the application can behave differently.

A Simple Example

Imagine a Spring Boot application.
Locally:
1
2
3
4
Java 17
MySQL localhost
Development configuration
Local environment variables
AWS:
1
2
3
4
5
6
Java 21
RDS database
Production configuration
Different environment variables
IAM permissions
VPC networking
The code hasn't changed.
But the environment has.

The Hidden Difference

Consider this:
1
2
3
4
5
6
7
Local

Application
↓
localhost:3306
↓
MySQL
After deployment:
1
2
3
4
5
6
7
AWS

Application
↓
Private Network
↓
RDS
Suddenly, the application needs to understand:
  • Database connectivity
  • Security groups
  • Credentials
  • DNS
  • Network routing
  • Runtime configuration
The application didn't suddenly become bad.
Its assumptions changed.

Configuration Is Part of the Application

Hardcoding configuration creates problems:
1
2
String dbUrl =
"jdbc:mysql://localhost:3306/mydb";
The application now assumes:
1
Database = localhost
That assumption may be valid locally but wrong in production.
A better approach is external configuration:
1
2
3
4
5
Application
↓
Environment Configuration
↓
Database
For example:
1
2
3
spring.datasource.url=${DB_URL}
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}
Now the application can run in different environments without changing the source code.

Dependencies Can Cause the Same Problem

Imagine your laptop has:
1
2
3
Python 3.12
Library X 2.4
Library Y 1.8
But your deployment uses:
1
2
3
Python 3.13
Library X 3.0
Library Y 2.0
Suddenly:
1
2
Local → Works ✓
AWS → Error ❌
This is why reproducible environments matter.
Your deployment should know exactly which runtime and dependencies it expects.

Environment Parity

A useful goal is:
1
2
3
4
5
Development
≈
Testing
≈
Production
They don't need to be identical.
But the important assumptions should be consistent.
For example:
1
2
3
4
5
Java Version
Database Type
Application Configuration
Dependency Versions
Environment Variables
should be intentionally managed.

Containers Can Help

One approach is packaging the application together with its runtime environment.
1
2
3
4
5
6
7
8
9
Application
+
Runtime
+
Dependencies
+
Configuration
↓
Container
Then the deployment environment doesn't have to recreate everything manually.
The idea becomes:
1
2
3
4
5
6
7
Build Once
↓
Test
↓
Deploy
↓
Run
This can make deployments much more predictable.

But Containers Don't Fix Everything

A container can solve environment consistency problems.
It cannot automatically solve:
1
2
3
4
5
6
❌ Wrong IAM permissions
❌ Incorrect security groups
❌ Missing environment variables
❌ Database connectivity
❌ DNS problems
❌ Incorrect AWS configuration
So:
1
2
3
4
5
Reproducible Application
+
Correct Infrastructure
=
Reliable Deployment
Both matter.

Find the Difference

When something works locally but fails in AWS, don't immediately rewrite the code.
Ask:
1
What changed?
Check systematically:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1. Runtime
↓
2. Dependencies
↓
3. Environment variables
↓
4. Configuration
↓
5. Network
↓
6. IAM permissions
↓
7. External services
↓
8. Database
This is often much faster than randomly changing things.

A Better Deployment Mindset

Instead of:
1
2
3
4
5
Write Code
↓
Deploy
↓
Hope
use:
1
2
3
4
5
6
7
8
9
10
11
Write Code
↓
Define Environment
↓
Test
↓
Package
↓
Deploy
↓
Verify
The goal isn't simply to make deployment possible.
The goal is to make deployment predictable.

The Real Lesson

“It works on my machine” isn't really a coding problem.
It's often an environment problem.
Your application depends on more than source code.
It depends on everything surrounding the code.
1
2
3
4
5
6
7
8
9
10
11
APPLICATION
|
+---------+---------+
| | |
Runtime Config Dependencies
| | |
+---------+---------+
|
Infrastructure
|
AWS
Understanding those relationships is an important part of becoming a cloud developer.

Final Takeaway

The best deployment isn't the one where:
“It worked once.”
It's the one where:
“We know exactly why it works, and we can reproduce it.”
So the next time someone says:
“It works on my machine.”
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article