Migrating from Heroku
This guide describes how to migrate an application from Heroku to AWS using Stacktape. With Stacktape, you can deploy your web services and databases in a similar way to Heroku, but with the benefits of AWS, such as:
- Lower costs.
- A dedicated VPC (private network) out of the box.
- A broader range of supported resources (containers, Lambda functions, batch jobs, DynamoDB tables, etc.).
You can continue to use other Heroku add-ons while your application is running on AWS by copying the appropriate environment variables. For example, if you use Heroku's SendGrid add-on, you can set SENDGRID_USERNAME
and SENDGRID_PASSWORD
in your service's environment variables.
Prerequisites
- A Stacktape account. If you do not have one, you can create one here.
- An AWS account connected to your Stacktape organization. For more information, see the Connect AWS Account guide.
Concepts mapping
The following table explains how some Heroku concepts map to Stacktape concepts.
Heroku | Stacktape |
---|---|
Web Process | Web service |
Worker Process | Worker service |
Dyno | An instance of your service |
Heroku Postgres | Relational database (with the option of a serverless database) |
Heroku Redis | Redis cluster (with the option of serverless Redis) |
Heroku Scheduler | Lambda function with a schedule event |
1. Writing stacktape.yml
The stacktape.yml
file is an infrastructure-as-code (IaC) file that specifies your services, databases, and other infrastructure resources. It also defines how to package them and what resources they have available. Additionally, it can specify automated actions to execute as part of the deployment process, such as testing or database migrations.
1.1. Create stacktape.yml
Create a stacktape.yml
file in your project's root directory.
For an easier authoring experience, you can use our interactive config editor or our VS Code extension.
1.2. Adding a web service
Since you are coming from Heroku, you will likely want to use a web service for your application. A web service is a simple container-based resource that runs your code with a public URL and a port exposed for HTTPS communication (with automatic SSL certificates), similar to a Heroku web dyno.
The web service definition contains everything Stacktape needs to know to build and package your application. You can use Heroku's buildpack builder (the same way Heroku builds and packages applications), which automatically detects the language and framework of your application and applies the correct buildpacks.
Alternatively, you can package your application by:
- Providing a Dockerfile
- Using our built-in, zero-config Stacktape Image Buildpack
For all packaging options, see the container packaging documentation.
Stacktape automatically injects a PORT
environment variable into the web service. All traffic is routed to this port, and you should bind your application to this port.
resources:appService:type: web-serviceproperties:packaging:type: external-buildpackproperties:sourceDirectoryPath: ./builder: heroku/builder:22# buildpacks:# - heroku/nodejsresources:cpu: 1memory: 1024
You can also run your application using a worker service (similar to a Heroku worker process dyno) or any other suitable Stacktape compute resource.
1.3. Adding a database
To replace your relational database (Heroku Postgres), you can use a relational database resource. Add it to your stacktape.yml
file alongside your web service, and choose the engine version and instance size according to your needs.
Here is a short overview of Heroku Postgres plans mapped to AWS RDS instances. For a complete list of all AWS instances, see the AWS documentation.
Heroku Plan | AWS Instance |
---|---|
Essential-0 | db.t3.micro: 2 vCPUs, 1 GB RAM |
Essential-1 | db.t3.small: 2 vCPUs, 2 GB RAM |
Essential-2 | db.t3.medium: 2 vCPUs, 4 GB RAM |
Standard-0 | db.t3.medium: 2 vCPUs, 4 GB RAM |
Standard-2 | db.m5.large: 2 vCPUs, 8 GB RAM |
Standard-3 | db.m5.xlarge: 4 vCPUs, 16 GB RAM |
Standard-4 | db.m5.2xlarge: 8 vCPUs, 32 GB RAM |
Standard-5 | db.r5.2xlarge: 8 vCPUs, 64 GB RAM |
Standard-6 | db.r5.4xlarge: 16 vCPUs, 128 GB RAM |
Standard-7 | db.r5.8xlarge: 32 vCPUs, 256 GB RAM |
Standard-8 | db.r5.12xlarge: 48 vCPUs, 384 GB RAM |
Standard-9 | db.r5.24xlarge: 96 vCPUs, 768 GB RAM |
Standard-10 | db.x1e.32xlarge: 128 vCPUs, 3904 GB RAM |
resources:appService:type: web-serviceproperties:packaging:type: external-buildpackproperties:sourceDirectoryPath: ./builder: heroku/builder:22resources:cpu: 1memory: 1024database:type: relational-databaseproperties:credentials:masterUserPassword: my-super-secret-passwordengine:type: postgresproperties:version: "16.3"primaryInstance:instanceSize: db.t3.micro
For storing passwords and other sensitive data, we recommend using secrets.
1.4. Environment variables and secrets
You can inject environment variables into your service by specifying them in the environment
list. You can use the $ResourceParam()
directive to inject information about other resources (such as a database URL or connection string) into your service. For sensitive values, you should create a secret and then reference it in your configuration using the $Secret()
directive. Stacktape will resolve these directives during deployment.
resources:appService:type: web-serviceproperties:packaging:type: external-buildpackproperties:sourceDirectoryPath: ./builder: heroku/builder:22resources:cpu: 1memory: 1024environment:- name: DATABASE_URLvalue: $ResourceParam('database', 'connectionString')# - name: DATABASE_PASSWORD# value: $Secret('my-database-password')database:type: relational-databaseproperties:credentials:masterUserPassword: $Secret('my-database-password')engine:type: postgresproperties:version: "16.3"primaryInstance:instanceSize: db.t3.micro
2. Deploy your app
Once you have your stacktape.yml
file in your repository, you are ready to deploy your application. Stacktape offers multiple ways to do this:
- Using the Stacktape CLI: Similar to the Heroku CLI. Requires Docker to be installed on your system. For more information, see Deploying with the CLI.
- GitOps (push-to-deploy): Set up an integration with GitHub or GitLab to deploy your application when there is a push to a specified branch. For more information, see Deploying with GitOps.
- Deploy from Git interactively: Interactively deploy from your GitHub or GitLab repository using the Stacktape Console. For more information, see Deploying from the Console.
- Deploy from any CI/CD: Deploy using any CI/CD system. For more information, see Deploying with a third-party CI/CD provider.
3. Migrating your data from PostgreSQL
If you have created a Stacktape PostgreSQL database, you may want to copy the data from your Heroku Postgres database.
This data migration process requires some downtime.
Put your Heroku app into maintenance mode so that no new data is written to the database during the copy. <HEROKU_APP_NAME>
is the name of the Heroku app that owns the Heroku Postgres add-on.
heroku maintenance:on --app <HEROKU_APP_NAME>
Create a backup of your Heroku Postgres database.
heroku pg:backups:capture --app <HEROKU_APP_NAME>
Download the backup. This will download a file named latest.dump
to your local machine.
heroku pg:backups:download --app <HEROKU_APP_NAME>
Import latest.dump
into your Stacktape Postgres database. The value for <CONNECTION_STRING>
can be found in the Stacktape Console.
pg_restore --verbose --no-acl --no-owner -d <CONNECTION_STRING> latest.dump
If your database is larger than 20 GB or under heavy load, use the instructions in the Heroku documentation to create a backup of your data. After that has completed, you can use the same pg_restore
command above to import the data.
Consider using the --jobs
flag with the pg_restore
command to reduce the time required for the restore.
4. Migrating a domain
If your Heroku app uses a custom domain, you have two options:
-
Manage your domain with your current DNS provider: You can continue to use your current DNS provider with Stacktape. However, you will need to create or import a custom TLS certificate in AWS Certificate Manager and reference it using
customCertificateArn
in your web service's domain configuration. After that, you can manually point your DNS record to your application's URL. For more information, see Using a third-party DNS provider. -
Manage your domain with Route 53 and Stacktape: You can use Stacktape to assign your custom domain to your application during deployment. This takes the burden of manually managing DNS records off of you and gives you broad options for managing domains, such as automatically assigning custom subdomains to your development and testing environments. For more information, see Managing domains with Stacktape.
FAQ
How does auto-scaling work?
Web services auto-scale based on CPU and memory usage thresholds. For more information, see the web service auto-scaling documentation.
Can I monitor the health of my app?
Yes. Health is monitored out of the box. If a web service task (container) is deemed unhealthy (e.g., your app crashes due to a bug), it is automatically replaced with a healthy one.
You can also set up your own internal health checks. If a task fails a health check, it is deemed unhealthy and replaced.
Is my app available during updates?
Yes. When you deploy a new version of your application, Stacktape uses a rolling update strategy. This means that an old web service task is only removed when a new, healthy task has replaced it.
In addition to the rolling update strategy, you can also choose from multiple types of blue/green deployment strategies.
Can I use a CDN in front of my app?
Yes. Many applications can benefit from a CDN, which can offload your services by caching responses. This results in fewer requests to your application, which leads to less compute power being consumed and paid for. With Stacktape, you can enable a CDN with a single line of configuration.
Can I manage MongoDB Atlas clusters with Stacktape?
Yes. You can seamlessly manage MongoDB Atlas clusters with Stacktape.
Do you support other resources?
Yes. We support many resource types, including containers, Lambda functions, and batch jobs. See our documentation for more information.
Is Stacktape extensible?
Yes. In addition to the plethora of AWS and third-party resource types that Stacktape supports by default, you can also extend your infrastructure using the AWS CDK or Cloudformation.