“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
↓
ApplicationBut 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
+
PermissionsChange 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 variablesAWS:
1
2
3
4
5
6
Java 21
RDS database
Production configuration
Different environment variables
IAM permissions
VPC networkingThe code hasn't changed.
But the environment has.
The Hidden Difference
Consider this:
1
2
3
4
5
6
7
Local
Application
↓
localhost:3306
↓
MySQLAfter deployment:
1
2
3
4
5
6
7
AWS
Application
↓
Private Network
↓
RDSSuddenly, 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 = localhostThat assumption may be valid locally but wrong in production.
A better approach is external configuration:
1
2
3
4
5
Application
↓
Environment Configuration
↓
DatabaseFor 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.8But your deployment uses:
1
2
3
Python 3.13
Library X 3.0
Library Y 2.0Suddenly:
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
≈
ProductionThey 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 Variablesshould 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
↓
ContainerThen the deployment environment doesn't have to recreate everything manually.
The idea becomes:
1
2
3
4
5
6
7
Build Once
↓
Test
↓
Deploy
↓
RunThis 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 configurationSo:
1
2
3
4
5
Reproducible Application
+
Correct Infrastructure
=
Reliable DeploymentBoth 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. DatabaseThis is often much faster than randomly changing things.
A Better Deployment Mindset
Instead of:
1
2
3
4
5
Write Code
↓
Deploy
↓
Hopeuse:
1
2
3
4
5
6
7
8
9
10
11
Write Code
↓
Define Environment
↓
Test
↓
Package
↓
Deploy
↓
VerifyThe 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
|
AWSUnderstanding 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.”
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article