Stacktape

Sign up

Stacktape

Sign up



Migrating from Heroku

Introduction

This guide describes how to migrate your application running on Heroku to AWS using Stacktape. Using Stacktape, you can deploy your web services and databases similarly to deploying them on Heroku. Main reason for using AWS instead of Heroku are:

  • Save on the bill - AWS can be a lot cheaper compared to Heroku
  • your own VPC (private network) out of the box,
  • broader support of resources (containers, lambda functions, batch jobs, dynamo...).

It is possible to continue using other Heroku add-ons while your app is running on AWS by copying over the appropriate environment variables — e.g., if you are using Heroku’s Sendgrid add-on, set SENDGRID_USERNAME and SENDGRID_PASSWORD in your service environment variables.

Prerequisites

  1. You should have a Stacktape account. If you do not have a Stacktape account, create one here.
  2. You should have an AWS account connected to your Stacktape organization. Refer to this tutorial to see how to connect your AWS account.

Concepts mapping

The following table explains how some Heroku concepts map to the Stacktape concepts.

HerokuStacktape
Web Process (within a Heroku app)Web service
Worker Process (within a Heroku app)Worker service
DynoAn instance of your service
Heroku PostgresRelational database (also possibility of serverless database)
Heroku RedisRedis cluster (also possibility of serverless redis)
Heroku SchedulerLambda function with schedule event

1 - Writing stacktape.yml

Stacktape config file stacktape.yml is an infrastructure as a code (IaC) that specifies your services - how to package them and what resources they have available, along with your databases and all other infrastructure resources. Additionally, it can specify automated actions to execute as a part of the deployment process, such as testing or database migrations.

1.1 - Create stacktape.yml

Create config file stacktape.yml in your application's project directory.

For easier writing of the config, you can try to use our interactive config editor or use our VSCode editor extension.

1.2 - Adding web-service

Since you are coming from Heroku, you will probably want to use Web Service resource for your application. Web service is a simple container-based resource that runs your code with public URL and port exposed for HTTPS communication(automatic SSL out of the box), similar to Heroku's web dyno.

Your web service definition contains everything Stacktape needs to know including how to build and package your app. You can use Heroku's buildpacks builder(same way Heroku builds and packages apps), which automatically detects the language and the framework of your application and applies the correct buildpacks for building your application. Optionally, you can specify buildpacks yourself.

However, you can also choose to package app by:

For convenience, Stacktape automatically injects environment variable PORT into the web service.

All the traffic is routed to this port, and you should bind your application to this port. Refer to docs to see example.

Copy

resources:
appService:
type: web-service
properties:
packaging:
type: external-buildpack
properties:
sourceDirectoryPath: ./
builder: heroku/builder:22
# buildpacks:
# - heroku/nodejs
resources:
cpu: 1
memory: 1024

Content of stacktape.yml file in your project directory.

Alternatively, you can run your application using worker-service(similar to Heroku's worker process dyno) or any other suitable Stacktape compute resource.

1.3 - Adding database

To replace your relational database (Heroku Postgres), you can use relational database resource. Add it to the config alongside web service. Choose the engine version and instance size according to your needs.

Here is a short overview of Heroku Postgres instances mapping to AWS RDS instances. To see the complete list of all AWS instances, refer to AWS docs.

Heroku PlanAWS Instance
Essential-0: 1 GB, 20 connectionsdb.t3.micro: 2 vCPUs, 1 GB RAM
Essential-1: 10 GB, 20 connectionsdb.t3.small: 2 vCPUs, 2 GB RAM
Essential-2: 32 GB, 40 connectionsdb.t3.medium: 2 vCPUs, 4 GB RAM
Standard-0: 4 GB, 64 GB storage, 120 connectionsdb.t3.medium: 2 vCPUs, 4 GB RAM
Standard-2: 8 GB, 256 GB storage, 400 connectionsdb.m5.large: 2 vCPUs, 8 GB RAM
Standard-3: 15 GB, 512 GB storage, 500 connectionsdb.m5.xlarge: 4 vCPUs, 16 GB RAM
Standard-4: 30 GB, 768 GB storage, 500 connectionsdb.m5.2xlarge: 8 vCPUs, 32 GB RAM
Standard-5: 61 GB, 1 TB storage, 500 connectionsdb.r5.2xlarge: 8 vCPUs, 64 GB RAM
Standard-6: 122 GB, 1.5 TB storage, 500 connectionsdb.r5.4xlarge: 16 vCPUs, 128 GB RAM
Standard-7: 244 GB, 2 TB storage, 500 connectionsdb.r5.8xlarge: 32 vCPUs, 256 GB RAM
Standard-8: 488 GB, 3 TB storage, 500 connectionsdb.r5.12xlarge: 48 vCPUs, 384 GB RAM
Standard-9: 768 GB, 4 TB storage, 500 connectionsdb.r5.24xlarge: 96 vCPUs, 768 GB RAM
Standard-10: 1 TB, 8 TB storage, 500 connectionsdb.x1e.32xlarge: 128 vCPUs, 3904 GB RAM

Copy

resources:
appService:
type: web-service
properties:
packaging:
type: external-buildpack
properties:
sourceDirectoryPath: ./
builder: heroku/builder:22
resources:
cpu: 1
memory: 1024
database:
type: relational-database
properties:
credentials:
masterUserPassword: my-supper-password
engine:
type: postgres
properties:
version: "16.3"
primaryInstance:
instanceSize: db.t3.micro

Content of stacktape.yml file after adding database.

For storing password and other sensitive data we recommend to use secrets.

1.4 - Environment and Secrets

You can easily inject environment variables to access them in a service by specifying them in environment list. You can use $ResourceParam directive to inject information about other resources (such as database URL / connection string) into your service. For sensitive and secret values, you should create secrets first and then reference them in the config using $Secret directive. Stacktape resolved these directives during deployment.

Copy

resources:
appService:
type: web-service
properties:
packaging:
type: external-buildpack
properties:
sourceDirectoryPath: ./
builder: heroku/builder:22
resources:
cpu: 1
memory: 1024
environment:
- name: DATABASE_URL
value: $ResourceParam('database', 'connectionString')
# - name: DATABASE_PASSWORD
# value: $Secret('my-database-password')
database:
type: relational-database
properties:
credentials:
masterUserPassword: $Secret('my-database-password')
engine:
type: postgres
properties:
version: "16.3"
primaryInstance:
instanceSize: db.t3.micro

2 - Deploy your app

After you have Stacktape config in your repository, you are ready to deploy your app.

Stacktape offers multiple ways of deploying your application:

  1. Using Stacktape CLI - similar to using Heroku CLI. requires Docker to be installed on the system.
  2. GitOps (push-to-deploy) - setup integration with Github or Gitlab to deploy your app when there is a push to a specified repository branch.
  3. Deploy from Git interactively - interactively deploy from your Github or Gitlab repository using Stacktape.
  4. Deploy from any CI/CD - deploy using any CI/CD system.

3 - Migrating your data from PostgreSQL

If you have created a Render PostgreSQL database, you may want to copy the data from your Heroku Postgres database to Render.

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 Heroku app that owns the Heroku Postgres add-on.

This data migration process requires some downtime.

Copy

heroku maintenance:on --app <HEROKU APP NAME>

Create a backup of the data in your Heroku Postgres database.

Copy

heroku pg:backups:capture --app <HEROKU APP NAME>

Download the backup. This will download a file named latest.dump to your local computer.

Copy

heroku pg:backups:download --app <HEROKU APP NAME>

Import latest.dump into your Stacktape Postgres relational database. The value for <CONNECTION STRING> can be found in Stackape console:

  • In the console, go to "Projects",
  • select your project and stage,
  • On the project stage overview page, click on your database resource which should show you the details of the resource (including connectionString)

Copy

pg_restore --verbose --no-acl --no-owner -d <CONNECTION STRING> latest.dump

If your database is larger than 20GB or under heavy load, use instructions in Heroku docs to create a backup of your data. After that has completed, you can use the same pg_restore command above to import the data to your Stacktape Postgres database.

Consider using the --jobs flag available to the pg_restore command to reduce the time required for restore.

4 - Migrating a domain

If your Heroku app uses a custom domain, you have two options:

  1. Manage domains using your old DNS system - you can keep using your DNS system while using Stacktape with AWS. However, you will need to create/import a custom TLS certificate in AWS ACM and reference it using customCertificateArn in your web service domain configuration. After that, you can manually point your DNS record to your app URL. See our docs on using 3rd party DNS provider.

  2. Manage domains using Route53 DNS and Stacktape - you can use Stacktape to assign your custom domain name to your app during deployment. See our docs on managing domains with Stacktape. This takes the burden of manually managing DNS records off you. Additionally, it gives you broad options for managing domains: i.e. to automatically assign custom subdomains to your development and testing environments etc.

FAQ

How does auto scaling work?

Web Service auto scale based on CPU/Memory usage thresholds. For more info, refer to the web service docs on auto scaling.

Can I monitor health of my app?

Yes. Health is actually monitored out of the box. If your web service task(container) is deemed unhealthy(i.e your app crashes due to some bug), the task is automatically replaced with healthy one.

Moreover, you can easily set up your own internal health-checks. If a task fails this health-check, it is deemed unhealthy and replaced.

Is my app available during updates?

Yes. When you decide to deploy new version of your app(update to a new version), Stacktape uses rolling update strategy. This means that any old web service task(container) is only removed when a new healthy task replaced it.

Besides rolling update strategy, you can also choose from multiple types of BLUE/GREEN deployment strategies.

Can I use CDN in front of my app?

Yes. Many applications can benefit from CDN. CDN can offload your services by caching responses, which results in less requests coming to the app which leads to less compute power consumed and paid for. With Stacktape you can enable CDN with single line of config

Can I manage Atlas MongoDB clusters using Stacktape?

Yes. You can seamlessly manage Atlas MongoDB clusters using Stacktape.

Do you support other resources?

Yes. We support many resource types(container based, lambdas, batch jobs...) fitting all of your needs. See our docs.

Is Stacktape extensible?

Yes. Except for plethora of AWS and 3rd party resource types Stacktape integrates by default, you can also extend your infrastructure using AWS CDK or AWS Cloudformation.

Need help? Ask a question on Discord or info@stacktape.com.