Web Services
Overview
Web service is a running container with a public endpoint. Main features of web service are:
- scalability - automatically add/remove containers based on CPU or memory usage (within your specified thresholds),
- zero downtime deployments (including various Blue/Green strategies),
- multiple options to provide container image, including zero-config packaging of code for Typescript/Javascript, Python, Java and Go,
- easy domain management with SSL/TLS certificates,
- ability to offload containers by putting CDN(cache) in-front of your endpoint,
- no hassle with managing and patching servers or VMs,
- seamless connectivity with other resources.
Get started
Start with web service by trying one of our starter projects or checkout example web service
Starter projects
- (Typescript) ExpressJS with Postgres
- (Typescript) NestJS with Postgres
- (Typescript) NextJS SSR website
- (Typescript) NuxtJS SSR website
- (Python) Django API with Postgres
- (Python) Flask API with Postgres
- (Go) Gin API with Postgres
- (PHP) Laravel SSR website
- (Java) Spring Boot API with Postgres
- (Ruby) Ruby on Rails with Postgres
Example web service
Copy
import express from 'express';const app = express();app.get('/', async (req, res) => {res.send({ message: 'Hello' });});// for your use port number stored in PORT environment variable for your application// this environment variable is automatically injected by Stacktapeapp.listen(process.env.PORT, () => {console.info(`Server running on port ${process.env.PORT}`);});
Example server container written in Typescript
Copy
resources:webService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: src/main.tsresources:cpu: 2memory: 2048
Example web service config
Under the hood
Under the hood Stacktape uses AWS ECS(Elastic Container Service) to orchestrate your containers. Containers can be ran using Fargate or EC2 instances:
- Fargate - technology which allows you to run containers without having to manage servers or clusters. This means you don't have to worry about administration tasks such as scaling, VM security, OS security & much more.
- EC2 instances - VMs running on AWS
ECS Services are self healing - if your container instance dies for any reason, it is automatically replaced with a healthy instance. They auto-scale from the box(within configured boundaries) leveraging the AWS Application Auto Scaling service.
Depending on the chosen load balancing type, traffic to the web-service containers is delivered and distributed either using HTTP API gateway(default) or Application load balancer. Stacktape automatically creates these gateway/load balancer as a part of creation of web service.
When to use
If you are unsure which resource type is best suitable for your app, following table provides short comparison of all container-based resource types offered by Stacktape.
Resource type | Description | Use-cases |
---|---|---|
web-service | continuously running container with public endpoint and URL | public APIs, websites |
private-service | continuously running container with private endpoint | private APIs, services |
worker-service | continuously running container not accessible from outside | continuous processing |
multi-container-workload | custom multi container workload - you can customize accessibility for each container | more complex use-cases requiring customization |
batch-job | simple container job - container is destroyed after job is done | one-off/scheduled processing jobs |
Advantages
- Control over underlying environment - Web service can run any Docker image or image built using your own Dockerfile.
- Price for compute resources with predictable load - Compared to functions, web services are cheaper if your compute resource has a predictable load.
- Load-balanced and auto-scalable - Web services can automatically horizontally scale based on the CPU and Memory utilization.
- High availability - Web services run in multiple Availability Zones.
- Secure by default - Underlying environment is securely managed by AWS.
Disadvantages
Scaling speed - Unlike lambda functions that scale almost instantly, web service requires more time - from several seconds to few minutes to add another container.
Not fully serverless - While web services can automatically scale up and down, they can't scale to 0. This means, if your compute resource is unused, you are still paying for at least one instance (minimum ~$8/month)
Image
- Web Service is a running instance of a Docker image.
- The image of the container can be supplied in 4 different ways:
- images built using stacktape-image-buildpack
- images built using external-buildpack
- images built from the custom-dockerfile
- prebuilt-images
Environment variables
Most commonly used types of environment variables:
- Static - string, number or boolean (will be stringified).
- Result of a custom directive.
- Referenced property of another resource (using $ResourceParam directive). To learn more, refer to referencing parameters guide. If you are using environment variables to inject information about resources into your script, see also property connectTo which simplifies this process.
- Value of a secret (using $Secret directive).
Copy
resources:webService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: src/main.tsenvironment:- name: STATIC_ENV_VARvalue: my-env-var- name: DYNAMICALLY_SET_ENV_VARvalue: $MyCustomDirective('input-for-my-directive')- name: DB_HOSTvalue: $ResourceParam('myDatabase', 'host')- name: DB_PASSWORDvalue: $Secret('dbSecret.password')resources:cpu: 2memory: 2048
Healthcheck
The purpose of the container health check is to monitor the health of the container from the inside.
Once an essential container of an instance is determined UNHEALTHY, the instance is automatically replaced with a new one.
- Example: A shell command sends a
curl
request every 20 seconds to determine if the service is available. If the request fails (or doesn't return in 5 seconds), the command returns with non-zero exit code, and the healthcheck is considered failed.
Copy
resources:myWebService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: src/index.tsinternalHealthCheck:healthCheckCommand: ['CMD-SHELL', 'curl -f http://localhost/ || exit 1']intervalSeconds: 20timeoutSeconds: 5startPeriodSeconds: 150retries: 2resources:cpu: 2memory: 2048
Shutdown
- When a running web service instance is deregistered (removed), all running containers receive a
SIGTERM
signal. - By default, you then have 2 seconds to clean up. After 2 seconds, your process receives a
SIGKILL
signal. - You can set the timeout by using
stopTimeout
property (must be between 2 - 120 seconds). - Setting stop timeout can help you give container the time to "finish the job" or to "cleanup" when deploying new version of container or when deleting the service.
Copy
process.on('SIGTERM', () => {console.info('Received SIGTERM signal. Cleaning up and exiting process...');// Finish any outstanding requests, or close a database connection...process.exit(0);});
Cleaning up before container shutdown.
Logging
- Every time your code outputs (prints) something to the
stdout
orstderr
, your log will be captured and stored in a AWS CloudWatch log group. - You can browse your logs in 2 ways:
- Browse logs in the AWS CloudWatch console. To get direct link to your logs you have 2 options:
- Go to stacktape console. Link is among information about your stack and resource.
- You can use
stacktape stack-info
command.
- Browse logs using stacktape logs command that will print logs to the console.
- Browse logs in the AWS CloudWatch console. To get direct link to your logs you have 2 options:
- Please note that storing log data can become costly over time. To avoid excessive charges, you can configure
retentionDays
.
Forwarding logs
It is possible to forward logs to the third party services/databases. See page Forwarding logs for more information and examples.
Resources
In resources
section, you specify amounts of cpu/memory and EC2 instance types available to your service.
There are two ways to run your containers:
using Fargate
- Fargate is a serverless, pay-as-you-go compute engine for running containers without having to manage underlying instances (servers).
- With Fargate you only need to specify
cpu
andmemory
required for your service. - While slightly more expensive, using Fargate is often preferred in strictly regulated industries since running containers on Fargate meets the standards for PCI DSS Level 1, ISO 9001, ISO 27001, ISO 27017, ISO 27018, SOC 1, SOC 2, SOC 3 out of the box.
using EC2 instances
- EC2 instances are virtual machines (VMs) ran on AWS cloud.
- Containers are placed on the EC2 instances which are added and removed depending on service needs.
- You can choose instance type that suit your resource requirements the best.
Whether you chose to use Fargate or EC2 instances, your containers are running securely within your VPC.
Following applies when configuring resources
section of your service:
When specifing resources there are two underlying compute engines to use:
- Fargate - abstracts the server and cluster management away from the user, allowing them to run containers without managing the underlying servers, simplifying deployment and management of applications but offering less control over the computing environment.
- EC2 (Elastic Compute Cloud) - provides granular control over the underlying servers (instances).
By choosing
instanceTypes
you get complete control over the computing environment and the ability to optimize for specific workloads.
To use Fargate: Do NOT specify
instanceTypes
and specifycpu
andmemory
properties.To use EC2 instances: specify
instanceTypes
.
Using Fargate
If you do not specify instanceTypes
property in resources
section, Fargate is used to run your containers.
Copy
resources:myWebService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: src/index.tsresources:cpu: 0.25memory: 512
Example using Fargate
Using EC2 instances
If you specify instanceTypes
property in resources
section, EC2 instances are used to run your containers.
- EC2 instances are automatically added or removed to meet the scaling needs of your compute resource(see also
scaling
property). - When using
instanceTypes
, we recommend to specify only one instance type and to NOT setcpu
ormemory
properties. By doing so, Stacktape will set the cpu and memory to fit the instance precisely - resulting in the optimal resource utilization. - Stacktape leverages ECS Managed Scaling with target utilization 100%. This means that there are no unused EC2 instances(unused = not running your workload/service) running. Unused EC2 instances are terminated.
- Ordering in
instanceTypes
list matters. Instance types which are higher on the list are preferred over the instance types which are lower on the list. Only when instance type higher on the list is not available, next instance type on the list will be used. - For exhaustive list of available EC2 instance types refer to AWS docs.
To ensure that your containers are running on patched and up-to-date EC2 instances, your compute resource gets automatically re-deployed once a week(Sunday 03:00 UTC). Your compute resource stays available throughout this process.
Copy
resources:myWebService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: src/index.tsresources:instanceTypes:- c5.large
Example using EC2 instances
Placing containers on EC2
Stacktape aims to achieve 100% utilization of your EC2 instances. However this is not always possible and following behavior can be expected:
If you only specify one type in
instanceTypes
and you do NOT setmemory
andcpu
then Stacktape setsmemory
andcpu
to fit the EC2 instance type precisely(see also Default cpu and memory section).This means that if your service scales(new instance of service is added), new EC2 instance is added as well.
If you specify
cpu
andmemory
properties alongsideinstanceTypes
, they will be respected. If the EC2 instance is larger (has more resources) than specifiedcpu
andmemory
, AWS places instances of your service on available EC2 instances using binpack strategy. This strategy aims to put as many instances of your service on the available EC2 instances as possible(to maximize utilization).
Default cpu and memory
If you do not specify
cpu
then entire capacity of EC2 instance CPU is shared between containers running on the EC2 instance.If you do not specify
memory
thenmemory
is set to a maximum possible value so that all EC2 instance types listed ininstanceTypes
are able provide that amount of memory.In other words: Stacktape sets the memory so that the smallest instance type in
instanceTypes
(in terms of memory) is able to provide that amount of memory.
Scaling
In scaling
section, you can configure scaling behavior of your service. You can configure:
- Minimum and maximum amount of concurrently running instances of your service.
- Conditions which trigger the scaling (up or down) using a scaling policy.
Scaling policy
A scaling policy specifies CPU and memory metric thresholds which trigger the scaling process.
Depending on the thresholds, the compute resource can either scale out (add instances) or scale in (remove instances).
If both
keepAvgCpuUtilizationUnder
andkeepAvgMemoryUtilizationUnder
are used, the compute resource will scale-out if one of the metrics is above the target value. However, to scale in, both of these metrics need to be below their respective target values.Scaling policy is more aggressive in adding capacity then removing capacity. For example, if the policy's specified metric reaches its target value, the policy assumes that your application is already heavily loaded. So it responds by adding capacity proportional to the metric value as fast as it can. The higher the metric, the more capacity is added.
When the metric falls below the target value, the policy expects that utilization will eventually increase again. Therefore it slows down the scale-in process by removing capacity only when utilization passes a threshold that is far enough below the target value (usually 20% lower).
Copy
resources:myWebService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: src/index.tsresources:cpu: 0.5memory: 1024scaling:minInstances: 1maxInstances: 5scalingPolicy:keepAvgMemoryUtilizationUnder: 80keepAvgCpuUtilizationUnder: 80
Example usage of scaling configuration
Storage
- Each web service instance has access to its own ephemeral storage. It's removed after the web service instances is removed.
- It has a fixed size of 20GB.
- If you have 2 concurrently running web service instances, they do not share this storage.
- To store data persistently, consider using Buckets.
Accessing other resources
For most of the AWS resources, resource-to-resource communication is not allowed by default. This helps to enforce security and resource isolation. Access must be explicitly granted using IAM (Identity and Access Management) permissions.
Access control of Relational Databases is not managed by IAM. These resources are not "cloud-native" by design and have their own access control mechanism (connection string with username and password). They are accessible by default, and you don't need to grant any extra IAM permissions. You can further restrict the access to your relational databases by configuring their access control mode.
Stacktape automatically handles IAM permissions for the underlying AWS services that it creates (i.e. granting web services permission to write logs to Cloudwatch, allowing web services to communicate with their event source and many others).
If your compute resource needs to communicate with other infrastructure components, you need to add permissions manually. You can do this in 2 ways:
Using connectTo
- List of resource names or AWS services that this service will be able to access (basic IAM permissions will be granted automatically). Granted permissions differ based on the resource.
- Works only for resources managed by Stacktape in
resources
section (not arbitrary Cloudformation resources) - This is useful if you don't want to deal with IAM permissions yourself. Handling permissions using raw IAM role
statements can be cumbersome, time-consuming and error-prone. Moreover, when using
connectTo
property, Stacktape automatically injects information about resource you are connecting to as environment variables into your workload.
Copy
resources:photosBucket:type: bucketmyWebService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: src/index.tsconnectTo:# access to the bucket- photosBucket# access to AWS SES- aws:sesresources:cpu: 0.25memory: 512
By referencing resources (or services) in connectTo
list, Stacktape automatically:
- configures correct compute resource's IAM role permissions if needed
- sets up correct security group rules to allow access if needed
- injects relevant environment variables containing information about resource you are connecting to into the compute resource's runtime
- names of environment variables use upper-snake-case and are in form
STP_[RESOURCE_NAME]_[VARIABLE_NAME]
, - examples:
STP_MY_DATABASE_CONNECTION_STRING
orSTP_MY_EVENT_BUS_ARN
, - list of injected variables for each resource type can be seen below.
- names of environment variables use upper-snake-case and are in form
Granted permissions and injected environment variables are different depending on resource type:
Bucket
- Permissions:
- list objects in a bucket
- create / get / delete / tag object in a bucket
- Injected env variables:
NAME
,ARN
DynamoDB table
- Permissions:
- get / put / update / delete item in a table
- scan / query a table
- describe table stream
- Injected env variables:
NAME
,ARN
,STREAM_ARN
MongoDB Atlas cluster
- Permissions:
- Allows connection to a cluster with
accessibilityMode
set toscoping-workloads-in-vpc
. To learn more about MongoDB Atlas clusters accessibility modes, refer to MongoDB Atlas cluster docs. - Creates access "user" associated with compute resource's role to allow for secure credential-less access to the the cluster
- Allows connection to a cluster with
- Injected env variables:
CONNECTION_STRING
Relational(SQL) database
- Permissions:
- Allows connection to a relational database with
accessibilityMode
set toscoping-workloads-in-vpc
. To learn more about relational database accessibility modes, refer to Relational databases docs.
- Allows connection to a relational database with
- Injected env variables:
CONNECTION_STRING
,JDBC_CONNECTION_STRING
,HOST
,PORT
(in case of aurora multi instance cluster additionally:READER_CONNECTION_STRING
,READER_JDBC_CONNECTION_STRING
,READER_HOST
)
Redis cluster
- Permissions:
- Allows connection to a redis cluster with
accessibilityMode
set toscoping-workloads-in-vpc
. To learn more about redis cluster accessibility modes, refer to Redis clusters docs.
- Allows connection to a redis cluster with
- Injected env variables:
HOST
,READER_HOST
,PORT
Event bus
- Permissions:
- publish events to the specified Event bus
- Injected env variables:
ARN
Function
- Permissions:
- invoke the specified function
- invoke the specified function via url (if lambda has URL enabled)
- Injected env variables:
ARN
Batch job
- Permissions:
- submit batch-job instance into batch-job queue
- list submitted job instances in a batch-job queue
- describe / terminate a batch-job instance
- list executions of state machine which executes the batch-job according to its strategy
- start / terminate execution of a state machine which executes the batch-job according to its strategy
- Injected env variables:
JOB_DEFINITION_ARN
,STATE_MACHINE_ARN
User auth pool
- Permissions:
- full control over the user pool (
cognito-idp:*
) - for more information about allowed methods refer to AWS docs
- full control over the user pool (
- Injected env variables:
ID
,CLIENT_ID
,ARN
SNS Topic
- Permissions:
- confirm/list subscriptions of the topic
- publish/subscribe to the topic
- unsubscribe from the topic
- Injected env variables:
ARN
,NAME
SQS Queue
- Permissions:
- send/receive/delete message
- change visibility of message
- purge queue
- Injected env variables:
ARN
,NAME
,URL
Upstash Kafka topic
- Injected env variables:
TOPIC_NAME
,TOPIC_ID
,USERNAME
,PASSWORD
,TCP_ENDPOINT
,REST_URL
Upstash Redis
- Injected env variables:
HOST
,PORT
,PASSWORD
,REST_TOKEN
,REST_URL
,REDIS_URL
Private service
- Injected env variables:
ADDRESS
aws:ses
(Macro)
- Permissions:
- gives full permissions to aws ses (
ses:*
). - for more information about allowed methods refer to AWS docs
- gives full permissions to aws ses (
Using iamRoleStatements
- List of raw IAM role statement objects. These will be appended to the web service's role.
- Allows you to set granular control over your web service's permissions.
- Can be used to give access to any Cloudformation resource
Copy
resources:myWebService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: server/index.tsiamRoleStatements:- Resource:- $CfResourceParam('NotificationTopic', 'Arn')Effect: 'Allow'Action:- 'sns:Publish'resources:cpu: 2memory: 2048cloudformationResources:NotificationTopic:Type: 'AWS::SNS::Topic'
Load balancing
LoadBalancing
property is used to configure what type of entry point is used for distributing traffic to containers:
- Supported types of entry points are:
http-api-gateway
andapplication-load-balancer
.
http-api-gateway
(default)
- distributes traffic to the available containers randomly
- uses pay-per-use pricing model (~$1 for million requests)
- pay-per-use pricing model is ideal for most workloads but once you cross ~500,000 requests per day, it might be cheaper to use application-load-balancer
application-load-balancer
- distributes traffic to the available containers in a round robin fashion
- uses pricing which is combination of flat hourly charge(~$0.0252/hour) and used LCUs(Load Balancer Capacity Units)(~$0.08/hour)
- is eligible for free tier, for better understanding of pricing refer to AWS docs
Copy
resources:webService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: src/main.tsresources:cpu: 2memory: 2048loadBalancing:type: application-load-balancer # default is http-api-gateway
Deployment strategies
Using deployment strategies you configure the way your web-service is updated when deploying new version. By default,
rolling update is used. However
you can use deployment
property to choose different strategy.
- Using
deployment
you can update the web-service in live environment in a safe way - by shifting the traffic to the new version gradually. - Gradual shift of traffic gives you opportunity to test/monitor the workload during update and in a case of a problem quickly rollback.
- Deployment supports multiple strategies:
- Canary10Percent5Minutes - Shifts 10 percent of traffic in the first increment. The remaining 90 percent is deployed five minutes later.
- Canary10Percent15Minutes - Shifts 10 percent of traffic in the first increment. The remaining 90 percent is deployed 15 minutes later.
- Linear10PercentEvery1Minute - Shifts 10 percent of traffic every minute until all traffic is shifted.
- Linear10PercentEvery3Minutes - Shifts 10 percent of traffic every three minutes until all traffic is shifted.
- AllAtOnce - Shifts all traffic to the updated web-service at once.
- You can validate/abort deployment(update) using lambda-function hooks.
When using deployment, your web-service must use application-load-balancer load balancing type
Copy
resources:webService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: src/main.tsresources:cpu: 2memory: 2048loadBalancing:type: application-load-balancerdeployment:strategy: Canary10Percent5Minutes
Hook functions
You can use hooks to perform checks using lambda-functions.
Copy
resources:webService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: src/main.tsresources:cpu: 2memory: 2048loadBalancing:type: application-load-balancerdeployment:strategy: Canary10Percent5MinutesafterTrafficShiftFunction: validateDeploymentvalidateDeployment:type: functionproperties:packaging:type: stacktape-lambda-buildpackproperties:entryfilePath: src/validate-deployment.ts
Copy
import { CodeDeployClient, PutLifecycleEventHookExecutionStatusCommand } from '@aws-sdk/client-codedeploy';const client = new CodeDeployClient({});export default async (event) => {// read DeploymentId and LifecycleEventHookExecutionId from payloadconst { DeploymentId, LifecycleEventHookExecutionId } = event;// performing validations hereawait client.send(new PutLifecycleEventHookExecutionStatusCommand({deploymentId: DeploymentId,lifecycleEventHookExecutionId: LifecycleEventHookExecutionId,status: 'Succeeded' // status can be 'Succeeded' or 'Failed'}));};
Code of validateDeployment function
Test traffic listener
When using beforeAllowTraffic
hook you can use test listener(test port) to send test traffic to the new
version of workload before allowing any production traffic.
By default the test listener is automatically created on port 8080
.
Copy
resources:webService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: src/main.tsresources:cpu: 2memory: 2048loadBalancing:type: application-load-balancerdeployment:strategy: Canary10Percent5MinutesbeforeAllowTrafficFunction: testDeploymenttestDeployment:type: functionproperties:packaging:type: stacktape-lambda-buildpackproperties:entryfilePath: src/test-deployment.tsenvironment:- name: WEB_SERVICE_URLvalue: $ResourceParam('webService', 'url')- name: TEST_LISTENER_PORTvalue: 8080
Copy
import { CodeDeployClient, PutLifecycleEventHookExecutionStatusCommand } from '@aws-sdk/client-codedeploy';import fetch from 'node-fetch';const client = new CodeDeployClient({});export default async (event: { DeploymentId: string; LifecycleEventHookExecutionId: string }) => {const { DeploymentId: deploymentId, LifecycleEventHookExecutionId: lifecycleEventHookExecutionId } = event;try {// test new version by using test listener portawait fetch(`${process.env.WEB_SERVICE_URL}:${process.env.TEST_LISTENER_PORT}`);// validate result// do some other tests ...} catch (err) {// send FAILED status if error occurredawait client.send(new PutLifecycleEventHookExecutionStatusCommand({deploymentId,lifecycleEventHookExecutionId,status: 'Failed'}));throw err;}// send SUCCEEDED status after successful testingawait client.send(new PutLifecycleEventHookExecutionStatusCommand({deploymentId,lifecycleEventHookExecutionId,status: 'Succeeded'}));};
Code of testDeployment function
Default VPC connection
- Certain AWS services (such as Relational Databases) must be connected to a
VPC (Virtual private cloud) to be able to run. For stacks that include these resources, Stacktape
does 2 things:
- creates a default VPC
- connects the VPC-requiring resources to the default VPC.
- web services are connected to the default VPC of your stack by default. This means that web services can communicate
with resources that have their accessibility mode set to
vpc
without any extra configuration. - To learn more about VPCs and accessibility modes, refer to VPC docs, accessing relational databases, accessing redis clusters and accessing MongoDb Atlas clusters.
CORS
Cross-origin resource sharing (CORS) is a browser security feature that restricts cross-origin HTTP requests that are initiated from scripts running in the browser.
A cross-origin HTTP request is a request that is made to a different domain or a different subdomain than the one browser is currently on.
Example: If your website has domain mydomain.com and it communicates with your web-service
which has domain
api.mydomain.com then the browser must perform cross origin request when communicating with this web-service
.
There are two types of cross-origin requests:
Simple requests
- requests that do not require CORS preflight.
- To understand what is considered a simple request refer to Mozilla docs.
- You do not need to configure CORS on your gateway for these types of requests. However, responses from your
application should still include
Access-Control-Allow-Origin
header where the value of the header key is set to*
(any origin) or is set to the origins allowed to access that resource. Refer to Mozilla docs for more information.
NON-simple (preflighted) requests
- all cross origin requests that are not considered simple are NON-simple and require preflight requests.
- If you send NON-simple CORS requests from browser to your API, you can enable CORS which takes care of preflight requests, and sets the necessary response headers.
If you need to use NON-simple cross origin requests you can enable CORS. CORS can be enabled with a single line.
If you are handling CORS within your application, it is unnecessary to enable it within configuration.
You cannot use property cors
when using loadBalancing
type application-load-balancer
Copy
resources:myWebService:type: 'web-service'properties:resources:cpu: 2memory: 2048packaging:type: stacktape-image-buildpackproperties:entryfilePath: src/main.tscors:enabled: true
web-service with CORS enabled
You can additionally configure CORS headers by setting properties in cors configuration.
If you do not specify any additional properties, default CORS configuration is used:
AllowedMethods
: Inferred from methods used by integrations associated with the api gatewayAllowedOrigins
:*
AllowedHeaders
:Content-Type
,X-Amz-Date
,Authorization
,X-Api-Key
,X-Amz-Security-Token
,X-Amz-User-Agent
Custom domain names
If you do not have a custom domain and want one, read the section Registering domain on the Domains and TLS certificates page.
If you already have an existing domain and you wish to use it with your app, there are two approaches:
- Using Stacktape to manage domains and certs - you must use Route53 in your AWS account as your DNS.
- Using 3rd party DNS provider - such as GoDaddy, Cloudflare etc. You must handle domains and generate certificates yourself.
For more information about domain management options, refer to Domains and TLS certificates page.
Using Stacktape to manage domains and certs
Stacktape allows you to connect your custom domain names to some of your resources (Web Service, HTTP API Gateways, Application Load Balancers and Buckets with CDNs).
Connecting a custom domain to the resource does 2 things:
- Creates DNS records:
- If you use your custom domain with a resource, Stacktape automatically creates a DNS record (during deploy) pointing the specified domain name to the resource.
- Adds TLS certificates
- If the origin resource (HTTP API Gateway, Application Load Balancer or CDN) uses HTTPS protocol, Stacktape takes care of issuing and attaching correct (free, AWS-managed) certificate to the resource. This means, you do not have to deal with TLS termination as it is handled by the connected resource.
- If you want to use your own certificates, you can configure
customCertificateArns
.
To manage a custom domain, it first needs to be added to your AWS account. This means that a hosted zone (collection of records managed together for a given domain) for your domain exists in your AWS account and your domain registrar's name servers are pointing to it. To learn more, refer to Adding a domain guide.
Copy
resources:myWebService:type: web-serviceproperties:resources:cpu: 2memory: 2048packaging:type: stacktape-image-buildpackproperties:entryfilePath: src/main.tscustomDomains:- domainName: whatever.mydomain.com
Using 3rd party DNS
To use 3rd party provider follow these steps:
- Create/import a custom TLS certificate for your domain in AWS console. Copy certificate ARN; you will need it in the next step.
- After the certificate is validated (Issued), assign your domain to your resource:
- use the ARN of your certificate as customCertificateArn
- disable DNS record creation (because you are using third party DNS)
Copy
resources:apiService:type: web-serviceproperties:resources:cpu: 2memory: 2048packaging:type: stacktape-image-buildpackproperties:entryfilePath: src/main.tscustomDomains:- domainName: mydomain.comdisableDnsRecordCreation: truecustomCertificateArn: <<ARN_OF_YOUR_CERTIFICATE>>
After you deploy your web service, you can find the domain name in Stacktape console in:
Your project and stage > Click on your Web service resource to see its domain
Once you have the domain name, you can point DNS record to this domain using your DNS provider:
- Use ALIAS record type for root domains (i.e mydomain.com)
- Use CNAME record type for subdomains (i.e www.mydomain.com or staging.mydomain.com
CDN
You can configure AWS Cloudfront CDN (Content Delivery Network) to be in front of your web-service.
- CDN is a globally distributed network that can cache responses from your Web Service at the edge - close to your users.
- AWS Cloudfront has 205 edge locations on 6 continents.
- The CDN is used to:
- reduce latency & improve load times
- reduce bandwidth costs
- reduce the amount of traffic coming to the origin (Web Service containers)
- improve security
- CDN caches responses from the origin at the edge for specified amount of time.
- If the content requested by the client is in the CDN cache, the CDN immediately returns it to the client without making a request to the origin.
- If the content is NOT in the cache, the CDN makes a request to the Origin. The response from the origin is then forwarded to the client, and cached at the edge.
For information about using CDN refer to our CDN docs.
Copy
resources:webService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: src/main.tsresources:cpu: 2memory: 2048cdn:enabled: true
Using firewall
- You can use
web-app-firewall
to protect your resources from common web exploits that could affect application availability, compromise security, or consume excessive resources. - Web app firewall protects your application by filtering dangerous requests coming to your app. You can read more about the firewall in our docs.
To lean more, check web-app-firewall documentation.
Copy
resources:myFirewall:type: web-app-firewallproperties:scope: regionalwebService:type: web-serviceproperties:packaging:type: stacktape-image-buildpackproperties:entryfilePath: src/main.tsresources:cpu: 2memory: 2048useFirewall: myFirewall
Referenceable parameters
The following parameters can be easily referenced using $ResourceParam directive directive.
To learn more about referencing parameters, refer to referencing parameters.
Web service default domain name
- Usage:
$ResourceParam('<<resource-name>>', 'domain')
Web service default URL
- Usage:
$ResourceParam('<<resource-name>>', 'url')
Comma-separated list of custom domain names assigned to the Web Service (only available if you use custom domain names)
- Usage:
$ResourceParam('<<resource-name>>', 'customDomains')
Comma-separated list of custom domain name URLs (only available if you use custom domain names)
- Usage:
$ResourceParam('<<resource-name>>', 'customDomainUrls')
Default domain of the CDN distribution (only available if you DO NOT configure custom domain names for the CDN).
- Usage:
$ResourceParam('<<resource-name>>', 'cdnDomain')
Default url of the CDN distribution (only available if you DO NOT configure custom domain names for the CDN).
- Usage:
$ResourceParam('<<resource-name>>', 'cdnUrl')
Comma-separated list of custom domain names assigned to the CDN (only available if you configure custom domain names for the CDN).
- Usage:
$ResourceParam('<<resource-name>>', 'cdnCustomDomains')
Comma-separated list of custom domain name URLs of the CDN (only available if you configure custom domain names for the CDN).
- Usage:
$ResourceParam('<<resource-name>>', 'cdnCustomDomainUrls')
Pricing
You are charged for:
Virtual CPU / hour:
- depending on the region $0.04048 - $0.0696
Memory GB / hour:
- depending on the region $0.004445 - $0.0076
The duration is rounded to 1 second with a 1 minute minimum. To learn more, refer to AWS Fargate pricing.