AWS serves millions of applications, and for good reason — it is the most capable cloud platform available. But capability and simplicity are not the same thing. Many teams running standard web applications on EC2, ECS, or Elastic Beanstalk are paying for complexity they do not need: NAT gateways, ALB configuration, IAM policy management, and CloudWatch setup consume engineering hours that belong in the product backlog. If your application is a web service, a background worker, and a PostgreSQL database, you are likely maintaining more AWS infrastructure than your application actually requires.
This guide covers the practical steps to migrate from AWS to Out Plane — a PaaS with per-second billing, managed PostgreSQL, and GitHub-based deployments. The process is methodical, low-risk, and designed to leave your AWS environment intact until you are confident the migration is complete.
Before You Start: Migration Checklist
A successful migration from AWS starts with understanding exactly what you are moving. Before touching any infrastructure, work through this checklist.
Inventory your AWS services:
- List every service your application uses: EC2, ECS, Fargate, RDS, S3, CloudFront, Route 53, ALB/ELB, ACM, CloudWatch, SSM Parameter Store, SES, SNS, and any others
- Identify which services are required for your application to function, versus which were added over time and may be redundant
- Document your current architecture with instance types, database sizes, and traffic patterns
Map AWS services to Out Plane equivalents:
| AWS Service | Out Plane Equivalent |
|---|---|
| EC2 / ECS / Fargate | Application deployment (Dockerfile or Buildpacks) |
| RDS PostgreSQL | Managed PostgreSQL (versions 14–18) |
| ELB / ALB | Built-in load balancing (automatic) |
| Route 53 | Custom domain mapping (CNAME or A record) |
| ACM | Automatic SSL (provisioned on deployment) |
| CloudWatch | Built-in logs and metrics |
| IAM (app access) | Environment variables via console |
| S3 | External — keep S3 or migrate to alternatives |
| CloudFront | External CDN (optional, not required) |
| SES | External — replace with Resend, Postmark, or SendGrid |
Plan your migration window:
- Schedule the cutover during a low-traffic period
- Identify which team members need to be available
- Prepare a rollback plan: keep AWS running in parallel for at least one to two weeks after cutover
Create your Out Plane account:
Sign in at console.outplane.com using GitHub OAuth. No separate registration is required — your GitHub account is all you need to access the console.
Step 1: Prepare Your Application
Containerize Your Application
Out Plane builds applications using either a Dockerfile or Paketo Buildpacks. If your application does not already have a Dockerfile, you have two options.
Option A: Write a Dockerfile. This gives you full control over the build environment and is recommended for production applications.
Here is a Dockerfile for a Node.js application:
FROM node:20-alpine AS base
FROM base AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM base AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=deps /app/node_modules ./node_modules
COPY . .
EXPOSE 8080
ENV PORT=8080
CMD ["node", "server.js"]For Python applications:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8080
CMD ["gunicorn", "--bind", "0.0.0.0:8080", "app:application"]Option B: Use Buildpacks. If your application uses a standard runtime (Node.js, Python, Ruby, Go, Java, PHP), Paketo Buildpacks will detect it automatically. No Dockerfile required. Out Plane uses Buildpacks as the default build method if no Dockerfile is present.
Port configuration: Out Plane's default port is 8080. Verify your application listens on port 8080, or configure the port setting in the console to match your application's actual port.
Extract Your Environment Variables
Environment variables are almost certainly scattered across multiple AWS locations. Check each of these before you consider the extraction complete.
EC2 instances:
# Variables set in the OS environment
cat /etc/environment
# Variables passed via user data on launch
curl http://169.254.169.254/latest/user-dataSSM Parameter Store (most common for production EC2 configurations):
# List all parameters in a given path
aws ssm get-parameters-by-path \
--path "/your-app-name/" \
--with-decryption \
--query "Parameters[*].[Name,Value]" \
--output textECS task definitions:
In the AWS Console, navigate to ECS > Task Definitions > your task definition. Open the JSON view and locate the environment and secrets arrays. Copy all key-value pairs.
Alternatively, via CLI:
aws ecs describe-task-definition \
--task-definition your-task-definition-name \
--query "taskDefinition.containerDefinitions[0].environment"Elastic Beanstalk:
eb printenv --environment your-environment-nameCompile all extracted variables into a plain text file in KEY=VALUE format. You will paste this into Out Plane's Raw Edit input during deployment configuration.
Push Your Code to GitHub
Out Plane deploys directly from GitHub repositories. Make sure your latest production code — including any Dockerfile you created — is committed and pushed to GitHub.
git add Dockerfile
git commit -m "Add Dockerfile for Out Plane deployment"
git push origin mainIf your repository is private, Out Plane requests read access to your repositories during the GitHub OAuth flow. No additional configuration is needed.
Step 2: Sign In to Out Plane
Navigate to console.outplane.com and sign in with GitHub. The authorization flow grants Out Plane access to your repositories.
Take a few minutes to familiarize yourself with the console layout:
- Applications: Where you create and manage deployed services
- Databases: Where you provision managed PostgreSQL instances
- Domains: Where you configure custom domains
There is no CLI to install. All configuration happens through the console.
Step 3: Create Your Database
If you are migrating from RDS PostgreSQL, start with the database before deploying your application. This lets you run the data migration before cutting over application traffic.
- In the console, navigate to Databases
- Click Create Database
- Select PostgreSQL and choose the version that matches your RDS version (Out Plane supports versions 14 through 18)
- Select the Nuremberg region (the default region)
- Click Create
Once the database is ready, copy the connection URL. It will look like:
postgres://user:[email protected]:5432/dbname
Keep this URL at hand — you will use it both for the data migration in the next step and as the DATABASE_URL environment variable when you deploy your application.
Step 4: Migrate Your Data
Export from RDS
Create a backup of your RDS PostgreSQL database using pg_dump. Run this from your local machine or from an EC2 instance in the same VPC as your RDS instance for faster transfer.
pg_dump \
-h your-rds-endpoint.region.rds.amazonaws.com \
-U your_db_user \
-d your_database_name \
-Fc \
-f backup.dumpThe -Fc flag produces a custom-format dump that is compressed and supports parallel restore. For large databases, this format is significantly faster than plain SQL.
If your RDS instance is not publicly accessible (which is the correct security configuration), run pg_dump from an EC2 instance in the same VPC, then copy the dump file to your local machine:
scp ec2-user@your-ec2-ip:/path/to/backup.dump ./backup.dumpImport to Out Plane PostgreSQL
With your dump file on your local machine, restore it to the Out Plane PostgreSQL instance:
pg_restore \
--no-acl \
--no-owner \
-d "postgres://user:[email protected]:5432/dbname" \
backup.dumpThe --no-acl and --no-owner flags prevent errors caused by RDS-specific role configurations that do not exist in the Out Plane database.
For large datasets, pg_restore supports parallel jobs:
pg_restore \
--no-acl \
--no-owner \
--jobs=4 \
-d "postgres://user:[email protected]:5432/dbname" \
backup.dumpVerify Data Integrity
Before proceeding, confirm that the migration was successful.
Connect to the Out Plane database and run basic checks:
-- Compare row counts for critical tables
SELECT schemaname, tablename, n_live_tup
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC;
-- Verify key data exists
SELECT COUNT(*) FROM users;
SELECT COUNT(*) FROM orders;Run the same queries against your RDS instance and compare the results. If the counts match, the migration is complete. If there are discrepancies, review the pg_restore output for errors and re-run the import.
Step 5: Deploy Your Application
With your database in place and your data migrated, deploy the application.
- In the console, navigate to Applications and click Create Application
- Select your GitHub repository from the list
- Choose your branch (typically
mainorproduction) - Select your build method:
- Dockerfile if your repository contains a Dockerfile at the root
- Buildpacks if you want automatic detection (default)
- Set the Port to match your application's port (default: 8080)
- Under Environment Variables, click Raw Edit and paste your variables in
KEY=VALUEformat:
DATABASE_URL=postgres://user:[email protected]:5432/dbname
NODE_ENV=production
SESSION_SECRET=your-session-secret
API_KEY=your-api-keyReplace the DATABASE_URL with the Out Plane PostgreSQL connection URL from Step 3.
- Click Deploy Application
Watch the deployment status in the console:
- Queued — waiting for a build runner to become available
- Building — your Dockerfile or Buildpack is being executed
- Deploying — the built image is starting up
- Ready — your application is live
Once the status shows Ready, your application URL is displayed at the top of the deployment page. It will follow the format your-app-name.outplane.app. Open it in a browser and verify your application is responding correctly.
Step 6: Configure Scaling
Out Plane scales your application automatically within bounds you define. Set these before going to production.
In the application settings, locate the Scaling section:
- Minimum instances: Set to
1for production workloads to eliminate cold starts. Use0for staging environments to reduce cost. - Maximum instances: Set based on your expected peak traffic. Start with
3to5for most applications and adjust after observing actual traffic patterns.
Out Plane scales up as traffic increases and scales back down when it subsides. You pay only for the seconds instances are actively running.
For applications migrating from EC2, a single EC2 instance maps roughly to a minimum of 1 instance on Out Plane. If you were running multiple EC2 instances for redundancy, set your minimum to match.
Step 7: Custom Domain and DNS Cutover
Before cutting over DNS, verify your application is functioning correctly on the default .outplane.app URL. Test all critical flows: authentication, database reads and writes, file uploads, API responses.
When you are ready to point your domain to Out Plane:
For Subdomains (app.yourdomain.com)
In your DNS provider, update the CNAME record:
| Record | Host | Value |
|---|---|---|
| CNAME | app | domains-management.outplane.app |
Delete or replace the existing CNAME that pointed to your ALB endpoint (e.g., your-alb-12345.us-east-1.elb.amazonaws.com).
For Apex Domains (yourdomain.com)
Apex domains cannot use CNAME records per DNS specification. Use an A record instead:
| Record | Host | Value |
|---|---|---|
| A | @ | 49.13.46.108 |
Adding the Domain in the Console
In the Out Plane console, navigate to Domains and click Map Domain. Enter your custom domain. Out Plane will provision an SSL certificate automatically within minutes of DNS propagation.
No certificate management is required. ACM certificates, certificate renewals, and HTTPS redirect rules are handled by the platform.
DNS Propagation
DNS changes typically propagate within a few minutes to a few hours depending on your previous TTL settings. During propagation, some users may still reach AWS while others reach Out Plane. Keep both environments running in parallel until propagation is complete.
To verify DNS has propagated for your domain:
dig app.yourdomain.com CNAME
# or
nslookup app.yourdomain.comOnce the response shows domains-management.outplane.app, propagation is complete for that resolver.
Step 8: Verify and Monitor
With DNS pointing to Out Plane, run a thorough verification before decommissioning AWS.
Check application logs: In the console, navigate to your application and open the Logs tab. Look for errors, exceptions, or unexpected status codes in the minutes after cutover.
Monitor response times: Compare response times before and after migration. Most applications see similar or improved performance due to Out Plane's load balancing. Significant increases may indicate a database connection issue or missing environment variable.
Test critical user flows end to end:
- User registration and login
- Data creation and retrieval
- Any integrations with third-party services (payment processors, email providers, etc.)
- File uploads (if your application stores files — confirm they still reach S3 or your configured storage)
Keep AWS running in parallel. Do not decommission your AWS infrastructure until you have at least one to two weeks of stable operation on Out Plane. If a critical issue emerges, you can update DNS back to AWS in minutes. The cost of running AWS in parallel for two weeks is far lower than the cost of a failed migration with no recovery path.
Step 9: Decommission AWS Resources
Once you are confident the migration is complete and stable, decommission your AWS resources in this order:
- ECS services / EC2 instances: Stop and terminate your application servers. If using ECS, scale the service to 0 tasks first, then delete the service.
- Load balancers: Delete your ALB or ELB after confirming no traffic is hitting them (check CloudWatch metrics to verify zero requests).
- RDS instances: Take a final snapshot before deleting. The snapshot serves as a long-term backup even after the instance is gone.
- NAT gateways: These are often a significant cost driver. Delete them once your application servers are gone.
- VPC resources: Remove subnets, route tables, and the VPC itself once dependent resources are deleted.
- CloudWatch alarms and log groups: Clean up monitoring resources that are no longer relevant.
Resources to keep:
- S3 buckets: Continue using S3 for object storage. Update your application's
AWS_S3_BUCKETenvironment variable and AWS credentials in the Out Plane console as needed. - Route 53 hosted zones: Keep these if you manage other DNS records for your domain. You only need to remove or update the records that pointed to your ALB.
Reserved instance contracts: If you purchased EC2 or RDS reserved instances, check your contract terms before terminating. Reserved instances continue billing until the term expires regardless of whether the instance is running. Factor this into your migration timeline — running a reserved instance in parallel costs nothing incremental until its term ends.
What About S3, CloudFront, and SES?
Not every AWS service has a direct equivalent on Out Plane. Here is how to handle the services that remain.
S3
S3 is the best object storage service available and there is no reason to migrate away from it. Your application on Out Plane can continue writing to and reading from S3 using the same AWS SDK and credentials. Add your AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_S3_BUCKET environment variables to your Out Plane application via the console.
If you prefer not to maintain an AWS account solely for S3, alternatives include Cloudflare R2 (S3-compatible API, no egress fees), Backblaze B2, or any other S3-compatible provider.
CloudFront
Out Plane applications do not require a CDN for typical web application traffic. The platform handles request routing and load balancing at the edge automatically. For most applications serving under a few million requests per month, removing CloudFront will not affect user experience.
If your application serves significant volumes of static assets or media files from S3, keeping CloudFront in front of S3 is reasonable. Do not put CloudFront in front of your Out Plane application unless you have a specific performance requirement that justifies the additional complexity.
SES
AWS Simple Email Service does not have a built-in equivalent on Out Plane. The simplest replacements are:
- Resend: Modern API with generous free tier, best developer experience
- Postmark: Best deliverability for transactional email
- SendGrid: Established platform with extensive API coverage
Update your application's email-sending configuration to use the new provider's SMTP settings or API key. These are set as environment variables in the Out Plane console.
Cost Comparison: Before and After
The cost savings from leaving AWS depend on your specific configuration. Here is a representative example for a typical production web application.
Before — AWS monthly costs:
| Resource | Monthly Cost |
|---|---|
| EC2 t3.small (2x, with redundancy) | ~$30 |
| RDS db.t3.micro (PostgreSQL) | ~$25 |
| Application Load Balancer | ~$22 |
| NAT Gateway (1x, data processing) | ~$35 |
| CloudWatch Logs and Metrics | ~$10 |
| Data transfer (egress) | ~$15 |
| Total | ~$137/month |
This does not include the engineering time spent managing IAM policies, CloudWatch alarms, VPC configuration, and EC2 patching — commonly estimated at 10 to 20 hours per month for a small team.
After — Out Plane monthly costs:
| Resource | Monthly Cost |
|---|---|
| Application (per-second billing, 1 instance) | ~$15–25 |
| Managed PostgreSQL | ~$20–30 |
| Load balancing, SSL, monitoring | Included |
| Total | ~$35–55/month |
The financial difference is meaningful, but the operational difference matters more for most small teams: no NAT gateways, no IAM roles to debug, no CloudWatch alarm thresholds to tune, no VPC configuration to maintain.
Per-second billing compounds the savings for applications with variable traffic. An application that handles burst traffic during business hours and sits mostly idle overnight pays for only the seconds it is actively processing requests, not for provisioned capacity around the clock.
Summary
Migrating from AWS is a straightforward process for most web applications. The steps are:
- Inventory your AWS services and map them to Out Plane equivalents
- Prepare your application: Dockerfile or Buildpacks, environment variables extracted, code in GitHub
- Create your Out Plane database matching your RDS PostgreSQL version
- Migrate your data with
pg_dumpandpg_restore - Deploy your application from GitHub with environment variables configured
- Configure scaling bounds before production traffic arrives
- Cut over DNS with a CNAME or A record pointing to Out Plane
- Verify thoroughly and keep AWS running in parallel for one to two weeks
- Decommission AWS resources after confirming stable operation
Keep your S3 buckets and email provider — those services remain on AWS or their replacements. Everything else maps cleanly to Out Plane's platform.
The result is a simpler infrastructure footprint, lower monthly cost, and engineering hours returned to product development rather than infrastructure maintenance.
Ready to start? Sign in at console.outplane.com and connect your GitHub account.
Frequently Asked Questions
Does Out Plane support applications that currently run on EC2 without Docker?
Yes. Use Paketo Buildpacks (the default build method) and Out Plane will automatically detect your application's runtime — Node.js, Python, Ruby, Go, Java, PHP — and build a container image without a Dockerfile. If your application has unusual dependencies or a non-standard build process, writing a Dockerfile gives you full control.
Can I migrate from RDS MySQL to Out Plane?
Out Plane does not currently offer managed MySQL in the console. If your application uses MySQL, you can continue running your RDS MySQL instance while deploying your application on Out Plane — your application connects to RDS over the public internet using the existing connection string and credentials. PostgreSQL versions 14 through 18 are available as managed databases on Out Plane.
How does Out Plane handle zero-downtime deployments?
Out Plane deploys new versions of your application before taking down the old ones. Existing traffic continues routing to the running instances until the new deployment passes health checks, at which point traffic shifts to the new instances. This rolling deployment behavior requires no additional configuration.
What regions does Out Plane support?
The default region is Nuremberg, Germany. Multi-region deployment is available on enterprise plans for applications with specific latency requirements across geographies.
Do I need to update my application code for Out Plane?
In most cases, no. Out Plane is a standard container runtime. Your application runs unchanged as long as it listens on a configurable port and reads configuration from environment variables — which is standard practice for any twelve-factor application.
Can I keep some services on AWS and run my application on Out Plane?
Yes. This is the recommended approach for services like S3 and SES. Your Out Plane application connects to AWS services over the internet using your existing credentials, set as environment variables in the console. You do not need to migrate services that work well on AWS.