Stacktape

Sign up for freeSign up



Worker Services

Overview and basic concepts

  • Worker service is a computing resource - it runs your code. Worker service runs continuously and scales based on the CPU and RAM usage.

  • Worker service is not reachable from the internet. It has no ports exposed and runs securely within a Virtual Private Cloud (VPC).

  • Similarly to functions and batch jobs, worker services are serverless and fully managed. This means you don't have to worry about administration tasks such as provisioning and managing servers, scaling, VM security, OS security & much more.

  • The container image can be supplied in 3 different ways:

    • built automatically from your source code by Stacktape
    • built using a supplied Dockerfile by Stacktape
    • pre-built images

Under the hood

Under the hood Stacktape uses AWS ECS(Elastic Container Service) to orchestrate your containers. Containers are ran using Fargate, a 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.


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.

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 typeDescriptionUse-cases
web-servicecontinuously running container with public endpoint and URLpublic APIs, websites
private-servicecontinuously running container with private endpointprivate APIs, services
worker-servicecontinuously running container not accessible from outsidecontinuous processing
multi-container-workloadcustom multi container workload - you can customize accessibility for each containermore complex use-cases requiring customization
batch-jobsimple container job - container is destroyed after job is doneone-off/scheduled processing jobs

Advantages

  • Control over underlying environment - Worker service can run any Docker image or image built using your own Dockerfile.
  • Price for compute resources with predictable load - Compared to functions, worker services are cheaper if your compute resource has a predictable load.
  • Load-balanced and auto-scalable - Worker services can automatically horizontally scale based on the CPU and Memory utilization.
  • High availability - Worker 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, worker service requires more time - from several seconds to few minutes to add another container.

  • Not fully serverless - While worker 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)

Basic usage

Copy

resources:
myWorkerService:
type: worker-service
properties:
packaging:
type: stacktape-image-buildpack
properties:
entryfilePath: src/main.ts
resources:
cpu: 2
memory: 2048

Example worker service config

Copy

import myContinuouslyRunningApp from './my-app';
const app = myContinuouslyRunningApp();
app.run();

Example server container written in Typescript (main.ts)


WorkerService  API reference
type
Required
properties.packaging
Required
properties.resources
Required
properties.environment
properties.logging
properties.scaling
properties.internalHealthCheck
properties.connectTo
properties.iamRoleStatements
overrides

Image

Environment variables

Most commonly used types of environment variables:

Copy

resources:
myWorkerService:
type: worker-service
properties:
packaging:
type: stacktape-image-buildpack
properties:
entryfilePath: src/main.ts
environment:
- name: STATIC_ENV_VAR
value: my-env-var
- name: DYNAMICALLY_SET_ENV_VAR
value: $MyCustomDirective('input-for-my-directive')
- name: DB_HOST
value: $ResourceParam('myDatabase', 'host')
- name: DB_PASSWORD
value: $Secret('dbSecret.password')
resources:
cpu: 2
memory: 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.

ContainerHealthCheck  API reference
healthCheckCommand
Required
intervalSeconds
Default: 30
timeoutSeconds
Default: 5
retries
Default: 3
startPeriodSeconds

  • 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 healtcheck is considered failed.

Copy

resources:
myWorkerService:
type: worker-service
properties:
packaging:
type: stacktape-image-buildpack
properties:
entryfilePath: src/index.ts
internalHealthCheck:
healthCheckCommand: ['CMD-SHELL', 'curl -f http://localhost/ || exit 1']
intervalSeconds: 20
timeoutSeconds: 5
startPeriodSeconds: 150
retries: 2
resources:
cpu: 2
memory: 2048

Shutdown

  • When a running worker service instance is deregistered (removed), all running containers receive a SIGTERM signal.
  • You then have 30 seconds to clean up. After 30 seconds, your process receives a SIGKILL signal.

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 or stderr, your log will be captured and stored in a AWS CloudWatch log group.
  • You can browse your logs in 2 ways:
    • go to your worker service's log-group in the AWS CloudWatch console. You can use stacktape stack-info command to get a direct link.
    • use stacktape logs command that will print logs to the console
ContainerWorkloadContainerLogging  API reference
disabled
retentionDays
Default: 90

Resources

  • You must configure computing resources (CPU and RAM) for your worker service.
  • Configured resources are valid for every container instance in the worker service (if there are more than 1 instance running).
ContainerWorkloadResourcesConfig  API reference
cpu
memory

Copy

resources:
myWorkerService:
type: worker-service
properties:
packaging:
type: stacktape-image-buildpack
properties:
entryfilePath: src/index.ts
resources:
cpu: 0.25
memory: 512

Scaling

  • Configures scaling behavior of your worker service. You can configure:
    • Minimum and maximum amount of concurrently running instances of your compute resource.
    • Conditions which trigger the scaling (up or down) using a scaling policy.
ContainerWorkloadScaling  API reference
minInstances
Default: 1
maxInstances
Default: 1
scalingPolicy

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 and keepAvgMemoryUtilizationUnder 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).

ContainerWorkloadScalingPolicy  API reference
keepAvgCpuUtilizationUnder
Default: 80
keepAvgMemoryUtilizationUnder
Default: 80

Copy

resources:
myWorkerService:
type: worker-service
properties:
packaging:
type: stacktape-image-buildpack
properties:
entryfilePath: src/index.ts
resources:
cpu: 0.5
memory: 1024
scaling:
minInstances: 1
maxInstances: 5
scalingPolicy:
keepAvgMemoryUtilizationUnder: 80
keepAvgCpuUtilizationUnder: 80

Example usage of scaling configuration

Storage

  • Each worker service instance has access to its own ephemeral storage. It's removed after the worker service instances is removed.
  • It has a fixed size of 20GB.
  • If you have 2 concurrently running worker 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 worker 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: bucket
myWorkerService:
type: worker-service
properties:
packaging:
type: stacktape-image-buildpack
properties:
entryfilePath: src/index.ts
connectTo:
# access to the bucket
- photosBucket
# access to AWS SES
- aws:ses
resources:
cpu: 0.25
memory: 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 or STP_MY_EVENT_BUS_ARN,
    • list of injected variables for each resource type can be seen below.

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 to scoping-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
  • Injected env variables: CONNECTION_STRING

Relational(SQL) database

  • Permissions:
    • Allows connection to a relational database with accessibilityMode set to scoping-workloads-in-vpc. To learn more about relational database accessibility modes, refer to Relational databases docs.
  • 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 to scoping-workloads-in-vpc. To learn more about redis cluster accessibility modes, refer to Redis clusters docs.
  • 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
  • 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
  • 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

aws:ses(Macro)

  • Permissions:
    • gives full permissions to aws ses (ses:*).
    • for more information about allowed methods refer to AWS docs

Using iamRoleStatements

  • List of raw IAM role statement objects. These will be appended to the worker service's role.
  • Allow you to set granular control over your worker service's permissions.
  • Can be used to give access to any Cloudformation resource

Copy

resources:
myWorkerService:
type: worker-service
properties:
packaging:
type: stacktape-image-buildpack
properties:
entryfilePath: server/index.ts
iamRoleStatements:
- Resource:
- $CfResourceParam('NotificationTopic', 'Arn')
Effect: 'Allow'
Action:
- 'sns:Publish'
resources:
cpu: 2
memory: 2048
cloudformationResources:
NotificationTopic:
Type: 'AWS::SNS::Topic'

StpIamRoleStatement  API reference
Resource
Required
Sid
Effect
Action
Condition

Default VPC connection

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.

API reference

StpIamRoleStatement  API reference
Resource
Required
Sid
Effect
Action
Condition

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