{"id":29228393,"url":"https://github.com/restatedev/restate-holiday","last_synced_at":"2025-07-03T10:11:25.469Z","repository":{"id":209742347,"uuid":"718295358","full_name":"restatedev/restate-holiday","owner":"restatedev","description":"Simplified Step Function workflow example based on Restate using the Saga pattern.","archived":false,"fork":false,"pushed_at":"2024-06-14T08:02:52.000Z","size":141,"stargazers_count":6,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-06-14T23:55:02.404Z","etag":null,"topics":["saga-pattern","step-functions","workflow"],"latest_commit_sha":null,"homepage":"https://restate.dev","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/restatedev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-11-13T19:41:58.000Z","updated_at":"2024-06-14T08:02:56.000Z","dependencies_parsed_at":"2024-06-13T23:53:14.139Z","dependency_job_id":null,"html_url":"https://github.com/restatedev/restate-holiday","commit_stats":null,"previous_names":["restatedev/restate-holiday"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/restatedev/restate-holiday","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/restatedev%2Frestate-holiday","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/restatedev%2Frestate-holiday/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/restatedev%2Frestate-holiday/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/restatedev%2Frestate-holiday/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/restatedev","download_url":"https://codeload.github.com/restatedev/restate-holiday/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/restatedev%2Frestate-holiday/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263305287,"owners_count":23445867,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["saga-pattern","step-functions","workflow"],"created_at":"2025-07-03T10:10:48.217Z","updated_at":"2025-07-03T10:11:25.459Z","avatar_url":"https://github.com/restatedev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Documentation](https://img.shields.io/badge/doc-reference-blue)](https://docs.restate.dev)\n[![Examples](https://img.shields.io/badge/view-examples-blue)](https://github.com/restatedev/examples)\n[![Discord](https://img.shields.io/discord/1128210118216007792?logo=discord)](https://discord.gg/skW3AZ6uGd)\n[![Twitter](https://img.shields.io/twitter/follow/restatedev.svg?style=social\u0026label=Follow)](https://twitter.com/intent/follow?screen_name=restatedev)\n\n# Restate Holiday\n\nThis repository demonstrates a complex workflow on Restate with AWS Lambda. The example is based\non [AWS's Step Functions sample implementation](https://github.com/aws-samples/step-functions-workflows-collection/tree/main/saga-pattern-cdk)\nof a Holiday booking service using the Saga pattern.\n\nThe goal of this example is to show how you can easily move a fairly complex AWS Step Functions workflow into code\nusing Restate. Instead of designing a graph of operations including failure compensations, you can just execute steps\nimperatively, using try/catch/finally statements to do error control. You also don't need to make a distinction between\nworkflow and lambda code; everything is Lambda.\n\nThe original example has 9 Lambdas:\n\n- Reserve/Confirm/Cancel flight\n- Reserve/Confirm/Cancel car reservation\n- Process/Refund payment\n- Kick off the workflow (called by API gateway)\n\nAnd some other components:\n\n- API Gateway\n- A Step Function with 12 steps\n\nInstead, we have 4 Lambda deployments, each corresponding to a single service from the domain:\n\n- The [Trip service](./src/trips.ts), the entrypoint which orchestrates the whole thing, which you can call directly via\n  the Restate HTTP ingress endpoint\n- The [Flight service](./src/flights.ts), with methods for reserve/confirm/cancel\n- The [Car service](./src/cars.ts), with methods for reserve/confirm/cancel\n- The [Payment service](./src/payments.ts), with methods for process/refund\n\n## Prerequisites\n\nThis example assumes you have the following installed:\n\n- [A current version of Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)\n- [An AWS account](https://aws.amazon.com/) and sufficient permissions to deploy the required resources\n- [AWS CLI](https://aws.amazon.com/cli/)\n- [curl](https://curl.se)\n\n## Deploying the Holiday Service and a self-hosted Restate instance\n\nBy default, the Holiday CDK app will deploy two stacks: a self-hosted Restate instance, and the Holiday service stack.\n\n```shell\nnpx cdk deploy --context deploySelfHostedRestateEnvironment=true\n```\n\nNote the ingress endpoint URL output by the deployment - we will need this later on.\n\n```shell\nexport INGRESS=$(aws cloudformation describe-stacks \\\n    --stack-name RestateStack \\\n    --query \"Stacks[0].Outputs[?OutputKey=='RestateIngressUrl'].OutputValue\" \\\n    --output text)\n```\n\n### Cleanup\n\nWhen you are done testing, you can easily delete all created resources with the command (if you specified a prefix\nduring deployment, you will need to use the same value here too):\n\n```shell\nnpx cdk destroy --all\n```\n\n## Deploying on Restate Cloud\n\nVisit [the Restate website](https://restate.dev) to register for a Cloud account which allows you to create a free\nenvironment. Create an API key with either Admin or Full access role.\n\nCreate a secret in Secrets Manager to hold the authentication token. You can use the following command to save the key\nin Secrets Manager.\n\n```shell\nexport AUTH_TOKEN_ARN=$(aws secretsmanager create-secret \\\n    --name /restate-holiday/auth-token --secret-string ${RESTATE_AUTH_TOKEN} \\\n    --query ARN --output text\n)\n```\n\nOnce you have the ARN for the secret, deploying the Holiday demo app is as easy as:\n\n```shell\nnpx cdk deploy \\\n    --context cloudEnvironmentId=${ENVIRONMENT_ID} \\\n    --context authTokenSecretArn=${AUTH_TOKEN_ARN}\n```\n\nJust like with the self-hosted stack you can also specify a unique prefix if you wish to deploy multiple copies of these\nstacks to the same AWS account with `--context prefix=${USER}`. You can also save these context attributes in the\n`cdk.json` file to avoid repetition for subsequent CDK operations.\n\nYou can obtain the Restate ingress URL from the Restate Cloud UI.\n\n```shell\nexport INGRESS=https://...\n```\n\nYou are now ready to jump to [Invoking](#Invoking) and send some requests to the service.\n\nSee the [Restate Cloud documentation](https://docs.restate.dev/deploy/cloud) for more information about deploying to it.\n\n### Cleanup\n\nWhen you are done testing, you can easily delete all created resources with the command (if you specified a prefix or a\ndeployment mode during deployment, you will need to use the same values here too):\n\n```shell\nnpx cdk destroy \\\n    --context cloudEnvironmentId=${ENVIRONMENT_ID} \\\n    --context authTokenSecretArn=${AUTH_TOKEN_ARN}\n```\n\n## Deploying against local Restate\n\nRestate services don't care if they're running in a Lambda or not. You can start a local instance of the service and use\nlocal AWS credentials to interact with AWS resources.\n\n```shell\n# get stack outputs into your shell\neval $(aws cloudformation describe-stacks --stack RestateHolidayStack  --query \"Stacks[].Outputs[]\" | jq -r '.[] | \"export \" + .ExportName + \"=\" + .OutputValue')\nFLIGHTS_TABLE_NAME=${flightsTableName} CARS_TABLE_NAME=${carsTableName} PAYMENTS_TABLE_NAME=${paymentsTableName} npm run app-dev\n```\n\nAnd you can start a local Restate instance and discover the service:\n\n```shell\nnpx run @restatedev/restate-server\n```\n\nIn another shell, register the locally running service endpoint with Restate:\n\n```shell\nnpx run @restatedev/restate deployments register http://localhost:9080\n```\n\n## Invoking\n\nNote that we use the `-k` flag to skip certificate validation and make requests work against an ingress endpoint using a\nself-signed certificate. If you are calling Restate Cloud, or have a valid certificate deployed in front of your Restate\ningress, you can omit this flag.\n\n```shell\ncurl -k ${INGRESS}/trips/reserve --json '{}'\n```\n\nYou can cause a specific type of failure by making a request with one of the following failure types:\n\n- `failFlightsReservation`\n- `failFlightsConfirmation`\n- `failCarRentalReservation`\n- `failCarRentalConfirmation`\n- `failPayment`\n- `failNotification`\n\n```shell\ncurl -k ${INGRESS}/trips/reserve --json '{\"request\": {\"run_type\": \"failPayment\"}}'\n```\n\nYou may also provide a trip ID of your choice:\n\n```shell\ncurl -k ${INGRESS}/trips/reserve --json '{\"request\": {\"trip_id\": \"foo\"}}'\n```\n\nFinally, you can make an idempotent invocation by setting the `idempotency-key` header:\n\n```shell\ncurl -k ${INGRESS}/trips/reserve -H 'idempotency-key: \u003cunique-key\u003e' --json '{}'\n```\n\n## Observability\n\n### Logs\n\nThe Restate container deployed by the CDK construct will publish its logs to CloudWatch logs. You can view them in the\nconsole or follow them from a terminal using the AWS CLI:\n\n```shell\naws logs tail /restate-holiday/restate-server --follow\n```\n\nIf you specified a deployment prefix, the log group will be called `/restate/\u003cprefix\u003e/restate`.\n\n### Traces\n\nThe self-hosted Restate container is configured to send traces to AWS X-Ray, by way of the AWS Distro for OpenTelemetry.\nYou should see traces in the X-Ray console including for health checks made by the load balancer. To filter just the\ntraces made to the demo Trips service, use a query like:\n\n```\nservice(id(name: \"trips\"))\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frestatedev%2Frestate-holiday","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frestatedev%2Frestate-holiday","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frestatedev%2Frestate-holiday/lists"}