{"id":342,"date":"2021-02-02T14:42:00","date_gmt":"2021-02-02T14:42:00","guid":{"rendered":"https:\/\/www.simplybusiness.co.uk\/go-routines-aws-lambda\/"},"modified":"2025-05-22T13:19:12","modified_gmt":"2025-05-22T13:19:12","slug":"go-routines-aws-lambda","status":"publish","type":"post","link":"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda","title":{"rendered":"Go routines for stateless AWS Lambda functions"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I love <a href=\"https:\/\/en.wikipedia.org\/wiki\/Serverless_computing\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"noopener noreferrer\" target=\"_blank\">serverless<\/a>. I&#8217;ve written about it before in my previous post on <a href=\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2020\/11\/third-party-logs-workflow\" data-type=\"post\" data-id=\"335\" >how to implement a third-party logs ingestion workflow<\/a>, but I now want to tackle the question: <em>&#8216;Is it possible to scale stateless serverless functions on the runtime as opposed to leveraging function concurrency?&#8217;<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In short, my answer is yes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Stateless vs stateful applications<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In the context of <a href=\"https:\/\/aws.amazon.com\/lambda\/\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"noopener noreferrer\" target=\"_blank\">AWS Lambda<\/a>, serverless makes it easier to scale up applications in multiple parallel executions. However, this also implies that stateful applications need to rely on some form of external storage to share memory. This is the only asynchronous way by which function invocations can \u2018communicate\u2019 with each other about their evolving status.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This adds to the complexity. It is somewhat harder to design a system that does not store its shared status on any form of local resource, be it volatile memory or the filesystem. But is it always necessary to avoid all forms of local sharing in the serverless runtime environment?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I believe the answer is no. Purists may shudder at this but I will try to make my case.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It really depends on whether the application you&#8217;re writing is stateful as opposed to stateless.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;re writing code that runs periodically and perpetually, with a need to communicate its evolving status, (and this is what I mean by stateful) then pushing the runtime for more parallelism is not an idea that will significantly simplify your application design. You&#8217;ll still need to have external storage in which to track the status, as the runtime existence is ephemeral and bound in time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If instead your application is stateless, then much can be gained by leveraging parallel executions on the runtime itself.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s consider an example. You want to write a scavenger function that periodically checks whether entries on a DynamoDB table are old enough to be deleted, so that the table is kept minimal and scan operations consume less read capacity. In short, you want to save on your DynamoDB bill.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is an example of a stateless application. The single application run &#8211; or Lambda function invocation &#8211; does not need to know anything about previous runs.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">By increasing the parallelism on the Lambda runtime environment, we get more speed, and possibly some savings on the Lambda bill.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If we were instead invoking the Lambda function multiple times in parallel, we would possibly be getting multiple cold starts, together with having to share an application status. That would be necessary to avoid having the same segments in our DynamoDB table being read by different Lambda invocations, thus giving up the benefits of parallel execution. In short, we&#8217;d be introducing a status for a conceptually stateless invocation. It doesn\u2019t sound right.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Language considerations<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now this is where I get excited. Increasing the parallelism of code is something that can be done in any language supporting multithreading.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/go.dev\/\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"noopener noreferrer\" target=\"_blank\">Golang<\/a> has been my language of choice, because I think the Go pattern of sharing memory by communicating fits very well with stateless AWS Lambda functions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Go support for cheap routines and channels is outstanding. Together with the support for context cancellation provided by the <a href=\"https:\/\/pkg.go.dev\/context\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"noopener noreferrer\" target=\"_blank\">package context<\/a>, it makes a great candidate language for programming a parallel function for the Lambda runtime.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.tech.sb\/\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"noopener noreferrer\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"256\" src=\"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/sb-tech-site-technology.webp?w=768\" alt=\"sb-tech-site-technology\" class=\"wp-image-9605\" srcset=\"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/sb-tech-site-technology.webp 768w, https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/sb-tech-site-technology.webp?resize=150,50 150w\" sizes=\"auto, (max-width: 768px) 100vw, 768px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">The parallel implementation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s revisit the example of the scavenger function. How do we translate our thoughts into code?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s the code sample for our implementation, and some guidelines for interpreting the code snippet:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"wp-block-list-item\">The Lambda handler is conceptually divided in two blocks: One reads items from the DynamoDB table, while the other deals with deleting them.<\/li>\n\n\n\n<li class=\"wp-block-list-item\">Both reads and deletions are parallelised.<\/li>\n\n\n\n<li class=\"wp-block-list-item\">A channel is used to send items from read to deletion.<\/li>\n\n\n\n<li class=\"wp-block-list-item\">The channel is closed when the reading phase is complete, without having to rely on knowing exactly how many items have been read.<\/li>\n\n\n\n<li class=\"wp-block-list-item\">Context objects are used to expire routines without leaking them on the Lambda execution timeout expiration.<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code has-white-color has-dark-800-background-color has-text-color has-background has-link-color wp-elements-dd3f2422b6dda68b63cf5e6230086f4b\" style=\"border-radius:8px;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)\"><code>package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"strconv\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com\/aws\/aws-lambda-go\/lambda\"\n\t\"github.com\/aws\/aws-sdk-go\/aws\"\n\t\"github.com\/aws\/aws-sdk-go\/aws\/awserr\"\n\t\"github.com\/aws\/aws-sdk-go\/aws\/session\"\n\t\"github.com\/aws\/aws-sdk-go\/service\/dynamodb\"\n\t\"github.com\/aws\/aws-sdk-go\/service\/dynamodb\/dynamodbattribute\"\n\t\"github.com\/remeh\/sizedwaitgroup\"\n)\n\nvar svc *dynamodb.DynamoDB\n\nfunc init() {\n\tsess := session.Must(session.NewSession())\n\tsvc = dynamodb.New(sess)\n}\n\ntype TableItem struct {\n\tWorkerId           int    `dynamodbav:\",string\"`\n\tStartTime          string `dynamodbav:\",string\"`\n\tStartExecutionTime string `dynamodbav:\",string\"`\n\tEndTime            string `dynamodbav:\",string\"`\n\tPaginationToken    string `dynamodbav:\",string\"`\n\tCompleted          int    `dynamodbav:\",string\"`\n}\n\nfunc HandleRequest(ctx aws.Context) {\n\tdeadline, _ := ctx.Deadline()\n\tlog.Println(\"Setting the parent context to control all context supporting operations.\")\n\tctx, cancel := context.WithDeadline(ctx, deadline)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Defers the context cancellation so that all the routines, that can be cancelled upon the context being so, are and do not leak resources.<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-dark-800-background-color has-text-color has-background has-link-color wp-elements-95ff896700d27b963c7367e3e9025232\" style=\"border-radius:8px;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)\"><code>\tdefer cancel()\n\n\tlog.Println(\"Reading DynamoDb table name from the Environment\")\n\tWorkersTableName := os.Getenv(\"WorkersTableName\")\n\n\tlog.Println(\"Setting the total number of segments in which to split the DynamoDb table scanning operations.\")\n\ttotalSegments, convErr := strconv.Atoi(os.Getenv(\"TotalSegments\"))\n\tif convErr != nil {\n\t\tlog.Fatalf(\"Fatal error occurred when trying to convert \"TotalSegments\" environment variable from string to int. Error message was: %s\", convErr)\n\t}\n\n\tlog.Println(\"Creating the channel onto which to push the items read from the table.\")\n\treadChannel := make(chan TableItem, 3*totalSegments) \/\/we want this channel to be buffered so that the sender is not blocked if no receivers are ready.<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The scan can be parallelised among multiple readers with a set number of segments. The <code>segment<\/code> and <code>totalSegments<\/code> can be set as part of the input fields. The scanned items are made available on the <code>readChannel<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-dark-800-background-color has-text-color has-background has-link-color wp-elements-19586608ebd803695044c2dc45280e2b\" style=\"border-radius:8px;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)\"><code>\treadRoutine := func(ctx *aws.Context, input *dynamodb.ScanInput, wg *sync.WaitGroup) {\n\t\tdefer wg.Done()\n\n\t\tselect {\n\t\tcase &lt;-(*ctx).Done():\n\t\t\tlog.Println((*ctx).Err())\n\t\t\treturn \/\/ returning not to leak the goroutine\n\t\tdefault:\n\t\t\tlog.Printf(\"Starting scan operation for segment number %v\", *(input.Segment))\n\t\t\tscanErr := svc.ScanPagesWithContext(*ctx, input, func(page *dynamodb.ScanOutput, lastPage bool) bool {\n\t\t\t\t\/\/fmt.Println(page.String()) \/\/This is to debug the retrieved page.\n\t\t\t\t\/\/fmt.Println(page.Items&#091;0])<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Here use a type <code>TableItem<\/code> that is application-defined and matches the structure of items from the DynamoDB table the application is reading from.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Unmarshall the scanned items to the slice of <code>TableItem<\/code> structures and send them to the <code>readChannel<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Once the <code>deleteItem<\/code> reads the object from the channel it can extract the relevant properties and add them to the <code>DeleteItemInput<\/code> structure it needs to build to send the delete request to DynamoDB.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It is not possible to simply have the scanned items passed over to the delete function as the <code>DeleteItemInput<\/code> structure is not compatible with the custom table-dependent item structure that is returned by the scan operation.<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-dark-800-background-color has-text-color has-background has-link-color wp-elements-ff7d330796a82ad32244fd4a9fcff57a\" style=\"border-radius:8px;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)\"><code>\t\t\t\tTableItems := &#091;]TableItem{}\n\t\t\t\tlog.Println(\"Unmarshalling the scanned page of items from the DynamoDB table into the scavenger-specific slice of TableItem objects.\")\n\t\t\t\tif readErr := dynamodbattribute.UnmarshalListOfMaps(page.Items, &amp;TableItems); readErr != nil {\n\t\t\t\t\tlog.Fatalf(\"Failed to unmarshall DynamoDb scanned items: Error message was %s\", readErr.(awserr.Error).Message())\n\t\t\t\t}\n\t\t\t\tlog.Println(\"Outputting the table items to the readChannel\")\n\t\t\t\tlog.Printf(\"The number of TableItems awaiting being output to the readChannel is: %v\", len(TableItems))\n\t\t\t\tfor _, readTableItem := range TableItems {\n\t\t\t\t\treadChannel &lt;- readTableItem\n\t\t\t\t\tlog.Printf(\"TableItem with WorkerId #%v has been sent to the readChannel.\", readTableItem.WorkerId)\n\t\t\t\t}\n\t\t\t\tlog.Println(\"All Table Items from the scanned page have been sent to the readChannel.\")\n\t\t\t\treturn !lastPage \/\/see https:\/\/github.com\/aws\/aws-sdk-go\/blob\/v1.35.37\/service\/dynamodb\/api.go#L5267 as to why this function returns the negated lastPage value.\n\t\t\t})\n\t\t\tif scanErr != nil {\n\t\t\t\tif aerr, ok := scanErr.(awserr.Error); ok {\n\t\t\t\t\tswitch aerr.Code() {\n\t\t\t\t\tcase dynamodb.ErrCodeProvisionedThroughputExceededException:\n\t\t\t\t\t\tfmt.Println(dynamodb.ErrCodeProvisionedThroughputExceededException, aerr.Error())\n\t\t\t\t\tcase dynamodb.ErrCodeResourceNotFoundException:\n\t\t\t\t\t\tfmt.Println(dynamodb.ErrCodeResourceNotFoundException, aerr.Error())\n\t\t\t\t\tcase dynamodb.ErrCodeRequestLimitExceeded:\n\t\t\t\t\t\tfmt.Println(dynamodb.ErrCodeRequestLimitExceeded, aerr.Error())\n\t\t\t\t\tcase dynamodb.ErrCodeInternalServerError:\n\t\t\t\t\t\tfmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error())\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tfmt.Println(aerr.Error())\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t\/\/ Print the error, cast err to awserr.Error to get the Code and\n\t\t\t\t\t\/\/ Message from an error.\n\t\t\t\t\tfmt.Println(scanErr.Error())\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Cast <code>totalSegments<\/code> to <code>int64<\/code> as that is the type expected by <code>SetSegment<\/code> and <code>SetTotalSegments<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-dark-800-background-color has-text-color has-background has-link-color wp-elements-5fd5e4528f1f605f2787b2da1f25edd6\" style=\"border-radius:8px;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)\"><code>\ttotalSegmentsInt64 := int64(totalSegments)\n\n\tvar wg sync.WaitGroup\n\n\tfor segment := int64(0); segment &lt; totalSegmentsInt64; segment++ {\n\t\tlog.Println(\"Creating the ScanInput object for each segment scanning routine.\")\n\t\tinput := &amp;dynamodb.ScanInput{\n\t\t\tTableName: aws.String(WorkersTableName),\n\t\t\tExpressionAttributeNames: map&#091;string]*string{\n\t\t\t\t\"#Comp\": aws.String(\"Completed\"),\n\t\t\t},\n\t\t\tExpressionAttributeValues: map&#091;string]*dynamodb.AttributeValue{\n\t\t\t\t\":NCompl\": {\n\t\t\t\t\tN: aws.String(\"1\"),\n\t\t\t\t},<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This is necessary to ensure that the old entries are also returned by the scan operation, as originally <code>Completed<\/code> was of type &#8216;string&#8217;.<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-dark-800-background-color has-text-color has-background has-link-color wp-elements-b73de47825caeef514ce18c1c4ac3def\" style=\"border-radius:8px;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)\"><code>\t\t\t\t\":SCompl\": {\n\t\t\t\t\tS: aws.String(\"1\"),\n\t\t\t\t},\n\t\t\t},\n\t\t\tFilterExpression: aws.String(\"#Comp = :NCompl OR #Comp = :SCompl\"),\n\t\t\t\/\/FilterExpression: aws.String(\"Completed = '1'\"),\n\t\t}\n\t\tinput.SetSegment(segment)\n\t\tinput.SetTotalSegments(totalSegmentsInt64)\n\t\tlog.Printf(\"Launching the scanning routine for segment #%v\", segment)\n\t\tlog.Printf(\"The scanning input is: %s\", input.String())\n\t\twg.Add(1)\n\t\tgo readRoutine(&amp;ctx, input, &amp;wg)\n\t}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The routine that is launched here is responsible for closing the communication channel between producers and consumers to avoid the Lambda running until the execution timeout expires. Given that we are listening on the communication channel with a &#8216;range&#8217; directive, without having to predict how many items are going to be sent on the channel and having to use another mechanism to communicate that the sending is over, the receiving routine can also end on retrieving all elements from the channel.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I believe that the devised solution of using a waitgroup before closing the communication channel and then allowing for the channel to be emptied is more elegant than using another out-of-band shared variable to check that we are done with sending. This is also more Go-like because we can share memory by communicating, rather than communicating by sharing memory.<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-dark-800-background-color has-text-color has-background has-link-color wp-elements-c654349e3d62f3a4cc4b40663401030c\" style=\"border-radius:8px;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)\"><code>\tgo func(wg *sync.WaitGroup) {\n\t\twg.Wait()\n\t\tclose(readChannel)\n\t}(&amp;wg)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Here we keep any utility variables that are used by date operations within the <code>deleteItem<\/code> function.<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-dark-800-background-color has-text-color has-background has-link-color wp-elements-ee30b9bfe60856a2e4c81e44ed8f1ce5\" style=\"border-radius:8px;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)\"><code>\tloc, _ := time.LoadLocation(\"UTC\")\n\tmaxItemLifeTime := 48<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now we have the section of the handler that is responsible for the deletion of the scanned items.<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-dark-800-background-color has-text-color has-background has-link-color wp-elements-b0f3c7ba8ab829a5ab2472f0a1d9ab94\" style=\"border-radius:8px;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)\"><code>\tdeleteItem := func(ctx *aws.Context, input *dynamodb.DeleteItemInput, StartExecutionTime string, swg *sizedwaitgroup.SizedWaitGroup) {\n\t\tdefer (*swg).Done()\n\t\tselect {\n\t\tcase &lt;-(*ctx).Done():\n\t\t\tlog.Println((*ctx).Err())\n\t\t\treturn \/\/ returning not to leak the goroutine\n\t\tdefault:\n\t\t\t\/\/if now - StartExecutionTime &gt;= 48hours then delete.\n\t\t\tif StartExecutionTime == \"\" {\n\t\t\t\tlog.Fatalf(\"The read item did not have a StartExecutionTime attribute. The related WorkerId is %s\", *input.Key&#091;\"WorkerId\"].N)\n\t\t\t}\n\t\t\tlog.Printf(\"Parsing the StartExecutionTime for item with WorkerId #%v\", *input.Key&#091;\"WorkerId\"].N)\n\t\t\tStartExecutionTime, dateError := time.Parse(time.RFC3339, StartExecutionTime)\n\t\t\tif dateError != nil {\n\t\t\t\tfmt.Println(dateError)\n\t\t\t}\n\t\t\tdiff := time.Now().In(loc).Sub(StartExecutionTime)\n\t\t\thoursdiff := int(diff.Hours())\n\n\t\t\tlog.Printf(\"Checking whether the item with WorkerId #%v should be deleted, which is happening if the StartExecutionTime timestamp is older than %v hours.\", *input.Key&#091;\"WorkerId\"].N, maxItemLifeTime)\n\t\t\tif hoursdiff &gt; maxItemLifeTime {\n\t\t\t\tlog.Printf(\"Deleting item with WorkerId #%v\", *input.Key&#091;\"WorkerId\"].N)\n\t\t\t\t_, deleteErr := svc.DeleteItemWithContext(*ctx, input)\n\t\t\t\t\/\/ Print the error, cast err to awserr.Error to get the Code and Message from an error.\n\t\t\t\tif deleteErr != nil {\n\t\t\t\t\tif aerr, ok := deleteErr.(awserr.Error); ok {\n\t\t\t\t\t\tswitch aerr.Code() {\n\t\t\t\t\t\tcase dynamodb.ErrCodeConditionalCheckFailedException:\n\t\t\t\t\t\t\tfmt.Println(dynamodb.ErrCodeConditionalCheckFailedException, aerr.Error())\n\t\t\t\t\t\tcase dynamodb.ErrCodeProvisionedThroughputExceededException:\n\t\t\t\t\t\t\tfmt.Println(dynamodb.ErrCodeProvisionedThroughputExceededException, aerr.Error())\n\t\t\t\t\t\tcase dynamodb.ErrCodeResourceNotFoundException:\n\t\t\t\t\t\t\tfmt.Println(dynamodb.ErrCodeResourceNotFoundException, aerr.Error())\n\t\t\t\t\t\tcase dynamodb.ErrCodeItemCollectionSizeLimitExceededException:\n\t\t\t\t\t\t\tfmt.Println(dynamodb.ErrCodeItemCollectionSizeLimitExceededException, aerr.Error())\n\t\t\t\t\t\tcase dynamodb.ErrCodeTransactionConflictException:\n\t\t\t\t\t\t\tfmt.Println(dynamodb.ErrCodeTransactionConflictException, aerr.Error())\n\t\t\t\t\t\tcase dynamodb.ErrCodeRequestLimitExceeded:\n\t\t\t\t\t\t\tfmt.Println(dynamodb.ErrCodeRequestLimitExceeded, aerr.Error())\n\t\t\t\t\t\tcase dynamodb.ErrCodeInternalServerError:\n\t\t\t\t\t\t\tfmt.Println(dynamodb.ErrCodeInternalServerError, aerr.Error())\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tfmt.Println(aerr.Error())\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfmt.Println(deleteErr.Error())\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\n\tlog.Println(\"Getting the max number of concurrent deletion routines from the environment.\")\n\tmaxDelRoutines, convErr := strconv.Atoi(os.Getenv(\"MaxDelRoutines\"))\n\tif convErr != nil {\n\t\tlog.Fatalf(\"An error occurred while attempting to convert environment variable \"MaxDelRoutines\" from string to int. Error message was: %s\", convErr)\n\t}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Here the idea is that if there is space in the <code>sizeWaitGroup<\/code> for a routine then launch it, but if not we need to wait until there is availability so as not to overwhelm the DynamoDB table, which can retain most of the capacity for the main read and update operations performed by the other Lambdas in the orchestration framework.<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-dark-800-background-color has-text-color has-background has-link-color wp-elements-f1673dad9c02ee7ee1749e5b8bcbe95d\" style=\"border-radius:8px;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)\"><code>\tlog.Println(\"Creating the sized wait group to synchronise the group of concurrent deletion routines and keep their number maxed out as provided by the Environment.\")\n\tswg := sizedwaitgroup.New(maxDelRoutines)\n\tfor readOutput := range readChannel {\n\t\tlog.Println(\"Waiting to add a new deletion routine to the sized synchronous wait group.\")\n\t\tswg.Add()\n\t\tlog.Println(\"Added a deletion routine.\")\n\t\tinput := &amp;dynamodb.DeleteItemInput{\n\t\t\tKey: map&#091;string]*dynamodb.AttributeValue{\n\t\t\t\t\"WorkerId\": {\n\t\t\t\t\tN: aws.String(strconv.Itoa(readOutput.WorkerId)),\n\t\t\t\t},\n\t\t\t\t\"StartTime\": {\n\t\t\t\t\tS: aws.String(readOutput.StartTime),\n\t\t\t\t},\n\t\t\t},\n\t\t\tTableName: aws.String(WorkersTableName),\n\t\t}\n\t\tDeleteStartExecutionTime := readOutput.StartExecutionTime\n\t\tlog.Printf(\"Launching deletion routine for item with WorkerId #%v\", *input.Key&#091;\"WorkerId\"].N)\n\t\tgo deleteItem(&amp;ctx, input, DeleteStartExecutionTime, &amp;swg)\n\t}\n\tswg.Wait()\n\tlog.Printf(\"All completed and older than %v hours items from the DynamoDB table %v have been successfully scanned and deleted.\", maxItemLifeTime, WorkersTableName)\n}\n\nfunc main() {\n\tlambda.Start(HandleRequest)\n}<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.tech.sb\/events\/\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"noopener noreferrer\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"256\" src=\"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/sb-tech-site-events.webp?w=768\" alt=\"sb-tech-site-events\" class=\"wp-image-9492\" srcset=\"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/sb-tech-site-events.webp 768w, https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/sb-tech-site-events.webp?resize=150,50 150w\" sizes=\"auto, (max-width: 768px) 100vw, 768px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Analysis<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For the analysis, a sequential version of the code above was used as a comparison &#8211; essentially the same code but with the parallelism variables set to <code>1<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then two specular copies of a DynamoDB table were prepared by leveraging AWS DataPipelines to export tables from S3 and reimport them. The tables contained approximately 130000 items and the functions conditionally deleted all but about 3300 items that did not meet the deletion criteria.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A number of tests were then run.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The parameterised settings used for the analysis are shown in the following table:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th class=\"has-text-align-left\" data-align=\"left\">Allocated memory (MB)<\/th><th class=\"has-text-align-left\" data-align=\"left\"><code>#<\/code>deletion routines<\/th><th class=\"has-text-align-left\" data-align=\"left\"><code>#<\/code>reading routines<\/th><th class=\"has-text-align-left\" data-align=\"left\">Billed duration (ms)<\/th><th class=\"has-text-align-left\" data-align=\"left\">Max memory used (MB)<\/th><th class=\"has-text-align-left\" data-align=\"left\">Billed cost ($)<\/th><\/tr><\/thead><tbody><tr><td class=\"has-text-align-left\" data-align=\"left\">128<\/td><td class=\"has-text-align-left\" data-align=\"left\">1<\/td><td class=\"has-text-align-left\" data-align=\"left\">1<\/td><td class=\"has-text-align-left\" data-align=\"left\">1965719<\/td><td class=\"has-text-align-left\" data-align=\"left\">95.5<code>*<\/code><\/td><td class=\"has-text-align-left\" data-align=\"left\">0.004128<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">512<\/td><td class=\"has-text-align-left\" data-align=\"left\">10<\/td><td class=\"has-text-align-left\" data-align=\"left\">10<\/td><td class=\"has-text-align-left\" data-align=\"left\">701119<\/td><td class=\"has-text-align-left\" data-align=\"left\">505<\/td><td class=\"has-text-align-left\" data-align=\"left\">0.005819<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">1024<\/td><td class=\"has-text-align-left\" data-align=\"left\">20<\/td><td class=\"has-text-align-left\" data-align=\"left\">10<\/td><td class=\"has-text-align-left\" data-align=\"left\">366121<\/td><td class=\"has-text-align-left\" data-align=\"left\">445<\/td><td class=\"has-text-align-left\" data-align=\"left\">0.006114<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">1024<\/td><td class=\"has-text-align-left\" data-align=\"left\">50<\/td><td class=\"has-text-align-left\" data-align=\"left\">20<\/td><td class=\"has-text-align-left\" data-align=\"left\">381811<\/td><td class=\"has-text-align-left\" data-align=\"left\">882<\/td><td class=\"has-text-align-left\" data-align=\"left\">0.006376<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">1024<\/td><td class=\"has-text-align-left\" data-align=\"left\">100<\/td><td class=\"has-text-align-left\" data-align=\"left\">100<\/td><td class=\"has-text-align-left\" data-align=\"left\">412897<\/td><td class=\"has-text-align-left\" data-align=\"left\">766<\/td><td class=\"has-text-align-left\" data-align=\"left\">0.006895<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">2048<\/td><td class=\"has-text-align-left\" data-align=\"left\">100<\/td><td class=\"has-text-align-left\" data-align=\"left\">50<\/td><td class=\"has-text-align-left\" data-align=\"left\">210355<\/td><td class=\"has-text-align-left\" data-align=\"left\">862<\/td><td class=\"has-text-align-left\" data-align=\"left\">0.007005<\/td><\/tr><tr><td class=\"has-text-align-left\" data-align=\"left\">2048<\/td><td class=\"has-text-align-left\" data-align=\"left\">100<\/td><td class=\"has-text-align-left\" data-align=\"left\">100<\/td><td class=\"has-text-align-left\" data-align=\"left\">189988<\/td><td class=\"has-text-align-left\" data-align=\"left\">709<\/td><td class=\"has-text-align-left\" data-align=\"left\">0.006327<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><code>*<\/code> The maximum memory used is the average consumed by the 3 consecutive sequential executions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s comment on the first two execution setups reported in the table; similar considerations can easily be deduced for the others.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The memory for the parallel Lambda function was set to 512MB and 128MB was allocated for the sequential function. This changes the billing unitary cost per ms, as per <code>AWS Lamdba pricing<\/code>, which on <code>eu-west-1<\/code> translates to:<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-dark-800-background-color has-text-color has-background has-link-color wp-elements-990806e9f65a43c70c6c5562b8d78d01\" style=\"border-radius:8px;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)\"><code>Parallel lambda: $0.0000000083 \/ ms\nSequential lambda: $0.0000000021 \/ ms<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The parallelism for both the reading and the deleting parts of our handler was set to <code>10<\/code> in the parallel Lambda function. This worked out well for the chosen amount of memory, but the same cannot be said for all the other tested setups (see table above).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The functions were executed with the same timeout, set to the currently allowed AWS maximum of 15 minutes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The parallel code successfully deleted all the items from the DynamoDB table in just over 700000ms, or about 12 minutes:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"900\" height=\"55\" src=\"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2021\/02\/report1.webp?w=900\" alt=\"Report results 1\" class=\"wp-image-12643\" srcset=\"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2021\/02\/report1.webp 900w, https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2021\/02\/report1.webp?resize=800,49 800w, https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2021\/02\/report1.webp?resize=768,47 768w, https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2021\/02\/report1.webp?resize=150,9 150w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">while the sequential implementation took three executions. Two of these ran down to the wire until the expiration of the execution timeout, thus a billed duration of 2 x 900000ms. The last one is shown below:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"900\" height=\"56\" src=\"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2021\/02\/report2.webp?w=900\" alt=\"Report results 2\" class=\"wp-image-12645\" srcset=\"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2021\/02\/report2.webp 900w, https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2021\/02\/report2.webp?resize=800,50 800w, https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2021\/02\/report2.webp?resize=768,48 768w, https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2021\/02\/report2.webp?resize=150,9 150w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In summary, the total costs for running the parallel and the sequential implementation were:<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-dark-800-background-color has-text-color has-background has-link-color wp-elements-ef3311aa51a890415ebfb535c5819939\" style=\"border-radius:8px;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)\"><code>Parallel: 701119ms*0.0000000083$\/ms = $0.005819\nSequential: (1800000+165719)ms*0.0000000021$\/ms = $0.004128<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The sequential implementation turns out to be cheaper by about 29% when it comes to total cost, albeit the execution takes 180% longer than in the first parallel case reported above.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The dataset allows us to draw a few more soft conclusions:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"wp-block-list-item\">Because DynamoDB is an HTTP database, we have a substantial impact on the billed duration, which only on average scales with the allocated memory and parallelism.<\/li>\n\n\n\n<li class=\"wp-block-list-item\">The billing incurred when processing sequentially is not matched by any of the parallel tests, however the sheer amount of time that the execution takes is significantly longer than any others.<\/li>\n\n\n\n<li class=\"wp-block-list-item\">The execution duration on average scales down with the allocated memory and parallelism, and seems to be more sensitive to the allocated memory, which for Lambda carries a relationship with CPU power more than to parallelism. The fact that at 1.8GB allocated memory a second virtual core is assigned to the function, as informally known from some <a href=\"https:\/\/reinvent.awsevents.com\/\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"noopener noreferrer\" target=\"_blank\">AWS reInvent<\/a> talks, seems to not carry any additional benefits.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Getting back to the initial question &#8211; whether there is a case for stretching the parallelism of the execution of a function on the Lambda runtime, I think the analysis provided suggests that it does.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In particular, if the focus is on reducing the execution duration of a stateless application, a Golang implementation seems like a good idea.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Happy coding!<\/p>\n\n\n\n<div id=\"nba-upsell-001\" class=\"wp-block-group has-azure-200-background-color has-background has-global-padding is-layout-constrained wp-container-core-group-is-layout-94e519ba wp-block-group-is-layout-constrained\" style=\"padding-top:var(--wp--preset--spacing--80);padding-right:var(--wp--preset--spacing--40);padding-bottom:var(--wp--preset--spacing--80);padding-left:var(--wp--preset--spacing--40)\">\n<h3 class=\"wp-block-heading has-text-align-center\">See our latest technology team opportunities<\/h3>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\">If you see a position that suits, why not apply today?<\/p>\n\n\n\n<div class=\"wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-a89b3969 wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button has-custom-font-size has-medium-font-size\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/www.simplybusiness.co.uk\/about-us\/careers\/tech\/\" style=\"padding-top:var(--wp--preset--spacing--20);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--20);padding-left:var(--wp--preset--spacing--30)\">Find out more<\/a><\/div>\n<\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-group has-azure-800-color has-azure-200-background-color has-text-color has-background has-link-color wp-elements-16ad430fbd6dcb711cba2ddbae941221 has-global-padding is-layout-constrained wp-container-core-group-is-layout-80fb368b wp-block-group-is-layout-constrained\" style=\"border-radius:8px;padding-top:var(--wp--preset--spacing--30);padding-right:var(--wp--preset--spacing--30);padding-bottom:var(--wp--preset--spacing--30);padding-left:var(--wp--preset--spacing--30)\">\n<p class=\"has-xxs-font-size wp-block-paragraph\">We create this content for general information purposes and it should not be taken as advice. Always take professional advice.<a href=\"https:\/\/www.simplybusiness.co.uk\/legal\/knowledge-centre-disclaimer\/\"> Read our full disclaimer<\/a><\/p>\n<\/div>\n\n\n\n<div id=\"newsletter-subscribe\" class=\"wp-block-group newsletter-subscribe is-layout-flow wp-block-group-is-layout-flow wp-block-block\" style=\"border-top-color:#cccccc;border-top-width:1px;padding-top:var(--wp--preset--spacing--80);padding-right:0;padding-bottom:var(--wp--preset--spacing--80);padding-left:0\">\n<p class=\"has-text-align-center has-dark-800-color has-text-color has-link-color has-medium-font-size wp-elements-ced002c3d2e03fde51d8880b5da0f3bb wp-block-paragraph\" style=\"margin-bottom:var(--wp--preset--spacing--50)\">A free monthly newsletter with the latest news and tools for small businesses and landlords.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-222c5d1d wp-block-buttons-is-layout-flex\" style=\"margin-bottom:var(--wp--preset--spacing--50)\">\n<div class=\"wp-block-button is-style-outline has-size-medium is-style-outline--1\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/www.simplybusiness.co.uk\/about-us\/newsletter-signup\/\">Subscribe to our newsletter<\/a><\/div>\n<\/div>\n\n\n\n<ul class=\"wp-block-social-links has-small-icon-size is-style-logos-only is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-a89b3969 wp-block-social-links-is-layout-flex\"><li class=\"wp-social-link wp-social-link-facebook  wp-block-social-link\"><a rel=\"noopener nofollow\" target=\"_blank\" href=\"https:\/\/www.facebook.com\/simplybusiness\" class=\"wp-block-social-link-anchor\" rel=\"noopener noreferrer\" target=\"_blank\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z\"><\/path><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">Follow Simply Business on Facebook<\/span><\/a><\/li>\n\n<li class=\"wp-social-link wp-social-link-x  wp-block-social-link\"><a rel=\"noopener nofollow\" target=\"_blank\" href=\"https:\/\/www.x.com\/simplybusiness\" class=\"wp-block-social-link-anchor\" rel=\"noopener noreferrer\" target=\"_blank\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z\" \/><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">Follow Simply Business on X<\/span><\/a><\/li>\n\n<li class=\"wp-social-link wp-social-link-youtube  wp-block-social-link\"><a rel=\"noopener nofollow\" target=\"_blank\" href=\"https:\/\/www.youtube.com\/user\/simplybusiness\" class=\"wp-block-social-link-anchor\" rel=\"noopener noreferrer\" target=\"_blank\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z\"><\/path><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">Subscribe to Simply Business Videos on Youtube<\/span><\/a><\/li>\n\n<li class=\"wp-social-link wp-social-link-linkedin  wp-block-social-link\"><a rel=\"noopener nofollow\" target=\"_blank\" href=\"https:\/\/www.linkedin.com\/company\/simply-business_39914\" class=\"wp-block-social-link-anchor\" rel=\"noopener noreferrer\" target=\"_blank\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z\"><\/path><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">Follow Simply Business on LinkedIn<\/span><\/a><\/li>\n\n<li class=\"wp-social-link wp-social-link-instagram  wp-block-social-link\"><a rel=\"noopener nofollow\" target=\"_blank\" href=\"https:\/\/www.instagram.com\/simplybusiness\" class=\"wp-block-social-link-anchor\" rel=\"noopener noreferrer\" target=\"_blank\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M12,4.622c2.403,0,2.688,0.009,3.637,0.052c0.877,0.04,1.354,0.187,1.671,0.31c0.42,0.163,0.72,0.358,1.035,0.673 c0.315,0.315,0.51,0.615,0.673,1.035c0.123,0.317,0.27,0.794,0.31,1.671c0.043,0.949,0.052,1.234,0.052,3.637 s-0.009,2.688-0.052,3.637c-0.04,0.877-0.187,1.354-0.31,1.671c-0.163,0.42-0.358,0.72-0.673,1.035 c-0.315,0.315-0.615,0.51-1.035,0.673c-0.317,0.123-0.794,0.27-1.671,0.31c-0.949,0.043-1.233,0.052-3.637,0.052 s-2.688-0.009-3.637-0.052c-0.877-0.04-1.354-0.187-1.671-0.31c-0.42-0.163-0.72-0.358-1.035-0.673 c-0.315-0.315-0.51-0.615-0.673-1.035c-0.123-0.317-0.27-0.794-0.31-1.671C4.631,14.688,4.622,14.403,4.622,12 s0.009-2.688,0.052-3.637c0.04-0.877,0.187-1.354,0.31-1.671c0.163-0.42,0.358-0.72,0.673-1.035 c0.315-0.315,0.615-0.51,1.035-0.673c0.317-0.123,0.794-0.27,1.671-0.31C9.312,4.631,9.597,4.622,12,4.622 M12,3 C9.556,3,9.249,3.01,8.289,3.054C7.331,3.098,6.677,3.25,6.105,3.472C5.513,3.702,5.011,4.01,4.511,4.511 c-0.5,0.5-0.808,1.002-1.038,1.594C3.25,6.677,3.098,7.331,3.054,8.289C3.01,9.249,3,9.556,3,12c0,2.444,0.01,2.751,0.054,3.711 c0.044,0.958,0.196,1.612,0.418,2.185c0.23,0.592,0.538,1.094,1.038,1.594c0.5,0.5,1.002,0.808,1.594,1.038 c0.572,0.222,1.227,0.375,2.185,0.418C9.249,20.99,9.556,21,12,21s2.751-0.01,3.711-0.054c0.958-0.044,1.612-0.196,2.185-0.418 c0.592-0.23,1.094-0.538,1.594-1.038c0.5-0.5,0.808-1.002,1.038-1.594c0.222-0.572,0.375-1.227,0.418-2.185 C20.99,14.751,21,14.444,21,12s-0.01-2.751-0.054-3.711c-0.044-0.958-0.196-1.612-0.418-2.185c-0.23-0.592-0.538-1.094-1.038-1.594 c-0.5-0.5-1.002-0.808-1.594-1.038c-0.572-0.222-1.227-0.375-2.185-0.418C14.751,3.01,14.444,3,12,3L12,3z M12,7.378 c-2.552,0-4.622,2.069-4.622,4.622S9.448,16.622,12,16.622s4.622-2.069,4.622-4.622S14.552,7.378,12,7.378z M12,15 c-1.657,0-3-1.343-3-3s1.343-3,3-3s3,1.343,3,3S13.657,15,12,15z M16.804,6.116c-0.596,0-1.08,0.484-1.08,1.08 s0.484,1.08,1.08,1.08c0.596,0,1.08-0.484,1.08-1.08S17.401,6.116,16.804,6.116z\"><\/path><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">Follow Simply Business on Instagram<\/span><\/a><\/li>\n\n<li class=\"wp-social-link wp-social-link-tiktok  wp-block-social-link\"><a rel=\"noopener nofollow\" target=\"_blank\" href=\"https:\/\/www.tiktok.com\/@simplybusiness\" class=\"wp-block-social-link-anchor\" rel=\"noopener noreferrer\" target=\"_blank\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 32 32\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M16.708 0.027c1.745-0.027 3.48-0.011 5.213-0.027 0.105 2.041 0.839 4.12 2.333 5.563 1.491 1.479 3.6 2.156 5.652 2.385v5.369c-1.923-0.063-3.855-0.463-5.6-1.291-0.76-0.344-1.468-0.787-2.161-1.24-0.009 3.896 0.016 7.787-0.025 11.667-0.104 1.864-0.719 3.719-1.803 5.255-1.744 2.557-4.771 4.224-7.88 4.276-1.907 0.109-3.812-0.411-5.437-1.369-2.693-1.588-4.588-4.495-4.864-7.615-0.032-0.667-0.043-1.333-0.016-1.984 0.24-2.537 1.495-4.964 3.443-6.615 2.208-1.923 5.301-2.839 8.197-2.297 0.027 1.975-0.052 3.948-0.052 5.923-1.323-0.428-2.869-0.308-4.025 0.495-0.844 0.547-1.485 1.385-1.819 2.333-0.276 0.676-0.197 1.427-0.181 2.145 0.317 2.188 2.421 4.027 4.667 3.828 1.489-0.016 2.916-0.88 3.692-2.145 0.251-0.443 0.532-0.896 0.547-1.417 0.131-2.385 0.079-4.76 0.095-7.145 0.011-5.375-0.016-10.735 0.025-16.093z\" \/><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">Follow Simply Business on TikTok<\/span><\/a><\/li><\/ul>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>I love serverless. I&#8217;ve written about it before in my previous post on how to implement a third-party logs ingestion workflow, but I now want to tackle the question: &#8216;Is it possible to scale stateless serverless functions on the runtime as opposed to leveraging function concurrency?&#8217; In short, my answer is yes. Stateless vs stateful [&hellip;]<\/p>\n","protected":false},"author":14,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"sb_hreflang":"","sb_hreflang_url":"","disable_breadcrumbs":false,"sb_breadcrumbs":[],"footnotes":""},"tags":[],"hidden-category":[],"coauthors":[243],"class_list":["post-342","post","type-post","status-publish","format-standard","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Go routines for stateless AWS Lambda functions<\/title>\n<meta name=\"description\" content=\"An analysis of stretching the parallelism of execution in the AWS Lambda Go 1.x runtime for stateless applications.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Go routines for stateless AWS Lambda functions\" \/>\n<meta property=\"og:description\" content=\"An analysis of stretching the parallelism of execution in the AWS Lambda Go 1.x runtime for stateless applications.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/\" \/>\n<meta property=\"og:site_name\" content=\"Simply Business UK\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/simplybusiness\" \/>\n<meta property=\"article:published_time\" content=\"2021-02-02T14:42:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-05-22T13:19:12+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/06\/golang.jpg\" \/>\n<meta name=\"author\" content=\"Vincenzo Zambianchi\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@simplybusiness\" \/>\n<meta name=\"twitter:site\" content=\"@simplybusiness\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Vincenzo Zambianchi\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/\"},\"author\":{\"@type\":\"Person\",\"name\":\"Vincenzo Zambianchi\",\"description\":\"\"},\"headline\":\"Go routines for stateless AWS Lambda functions\",\"datePublished\":\"2021-02-02T14:42:00+00:00\",\"dateModified\":\"2025-05-22T13:19:12+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/\"},\"wordCount\":1665,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.simplybusiness.co.uk\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/sb-tech-site-technology.webp?w=768\",\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/\",\"url\":\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/\",\"name\":\"Go routines for stateless AWS Lambda functions\",\"isPartOf\":{\"@id\":\"https:\/\/www.simplybusiness.co.uk\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/sb-tech-site-technology.webp?w=768\",\"datePublished\":\"2021-02-02T14:42:00+00:00\",\"dateModified\":\"2025-05-22T13:19:12+00:00\",\"description\":\"An analysis of stretching the parallelism of execution in the AWS Lambda Go 1.x runtime for stateless applications.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#primaryimage\",\"url\":\"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/sb-tech-site-technology.webp\",\"contentUrl\":\"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/sb-tech-site-technology.webp\",\"width\":768,\"height\":256,\"caption\":\"sb-tech-site-technology\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.simplybusiness.co.uk\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Go routines for stateless AWS Lambda functions\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.simplybusiness.co.uk\/#website\",\"url\":\"https:\/\/www.simplybusiness.co.uk\/\",\"name\":\"Simply Business UK\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/www.simplybusiness.co.uk\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.simplybusiness.co.uk\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.simplybusiness.co.uk\/#\/schema\/person\/77f91625e7ec1b88a7fca8910ce6c69f\",\"name\":\"rishvashah\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\/\/www.simplybusiness.co.uk\/wp-content\/themes\/simply-business\/dist\/images\/default-author-avatar.webp9df6147f02078f0218660330fdfbacf3\",\"url\":\"https:\/\/www.simplybusiness.co.uk\/wp-content\/themes\/simply-business\/dist\/images\/default-author-avatar.webp\",\"contentUrl\":\"https:\/\/www.simplybusiness.co.uk\/wp-content\/themes\/simply-business\/dist\/images\/default-author-avatar.webp\",\"caption\":\"rishvashah\"}},{\"@type\":\"PostalAddress\",\"@id\":\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#local-main-place-address\",\"streetAddress\":\"Hylo, 105 Bunhill Row\",\"addressLocality\":\"London\",\"postalCode\":\"EC1Y 8LZ\",\"addressCountry\":\"GB\"},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#local-main-organization-logo\",\"url\":\"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/logo.png\",\"contentUrl\":\"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/logo.png\",\"width\":533,\"height\":187,\"caption\":\"Simply Business UK\"}]}<\/script>\n<meta name=\"geo.placename\" content=\"London\" \/>\n<meta name=\"geo.region\" content=\"United Kingdom (UK)\" \/>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Go routines for stateless AWS Lambda functions","description":"An analysis of stretching the parallelism of execution in the AWS Lambda Go 1.x runtime for stateless applications.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/","og_locale":"en_GB","og_type":"article","og_title":"Go routines for stateless AWS Lambda functions","og_description":"An analysis of stretching the parallelism of execution in the AWS Lambda Go 1.x runtime for stateless applications.","og_url":"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/","og_site_name":"Simply Business UK","article_publisher":"https:\/\/www.facebook.com\/simplybusiness","article_published_time":"2021-02-02T14:42:00+00:00","article_modified_time":"2025-05-22T13:19:12+00:00","og_image":[{"url":"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/06\/golang.jpg","type":"","width":"","height":""}],"author":"Vincenzo Zambianchi","twitter_card":"summary_large_image","twitter_creator":"@simplybusiness","twitter_site":"@simplybusiness","twitter_misc":{"Written by":"Vincenzo Zambianchi","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#article","isPartOf":{"@id":"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/"},"author":{"@type":"Person","name":"Vincenzo Zambianchi","description":""},"headline":"Go routines for stateless AWS Lambda functions","datePublished":"2021-02-02T14:42:00+00:00","dateModified":"2025-05-22T13:19:12+00:00","mainEntityOfPage":{"@id":"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/"},"wordCount":1665,"commentCount":0,"publisher":{"@id":"https:\/\/www.simplybusiness.co.uk\/#organization"},"image":{"@id":"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#primaryimage"},"thumbnailUrl":"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/sb-tech-site-technology.webp?w=768","inLanguage":"en-GB","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/","url":"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/","name":"Go routines for stateless AWS Lambda functions","isPartOf":{"@id":"https:\/\/www.simplybusiness.co.uk\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#primaryimage"},"image":{"@id":"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#primaryimage"},"thumbnailUrl":"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/sb-tech-site-technology.webp?w=768","datePublished":"2021-02-02T14:42:00+00:00","dateModified":"2025-05-22T13:19:12+00:00","description":"An analysis of stretching the parallelism of execution in the AWS Lambda Go 1.x runtime for stateless applications.","breadcrumb":{"@id":"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/"]}]},{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#primaryimage","url":"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/sb-tech-site-technology.webp","contentUrl":"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/sb-tech-site-technology.webp","width":768,"height":256,"caption":"sb-tech-site-technology"},{"@type":"BreadcrumbList","@id":"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.simplybusiness.co.uk\/"},{"@type":"ListItem","position":2,"name":"Go routines for stateless AWS Lambda functions"}]},{"@type":"WebSite","@id":"https:\/\/www.simplybusiness.co.uk\/#website","url":"https:\/\/www.simplybusiness.co.uk\/","name":"Simply Business UK","description":"","publisher":{"@id":"https:\/\/www.simplybusiness.co.uk\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.simplybusiness.co.uk\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":"Person","@id":"https:\/\/www.simplybusiness.co.uk\/#\/schema\/person\/77f91625e7ec1b88a7fca8910ce6c69f","name":"rishvashah","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/www.simplybusiness.co.uk\/wp-content\/themes\/simply-business\/dist\/images\/default-author-avatar.webp9df6147f02078f0218660330fdfbacf3","url":"https:\/\/www.simplybusiness.co.uk\/wp-content\/themes\/simply-business\/dist\/images\/default-author-avatar.webp","contentUrl":"https:\/\/www.simplybusiness.co.uk\/wp-content\/themes\/simply-business\/dist\/images\/default-author-avatar.webp","caption":"rishvashah"}},{"@type":"PostalAddress","@id":"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#local-main-place-address","streetAddress":"Hylo, 105 Bunhill Row","addressLocality":"London","postalCode":"EC1Y 8LZ","addressCountry":"GB"},{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda\/#local-main-organization-logo","url":"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/logo.png","contentUrl":"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/05\/logo.png","width":533,"height":187,"caption":"Simply Business UK"}]},"geo.placename":"London","geo.region":"United Kingdom (UK)"},"parsely":{"version":"1.1.0","canonical_url":"https:\/\/simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda","smart_links":{"inbound":0,"outbound":0},"traffic_boost_suggestions_count":0,"meta":{"@context":"https:\/\/schema.org","@type":"NewsArticle","headline":"Go routines for stateless AWS Lambda functions","url":"http:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda","mainEntityOfPage":{"@type":"WebPage","@id":"http:\/\/www.simplybusiness.co.uk\/about-us\/tech\/2021\/02\/go-routines-aws-lambda"},"thumbnailUrl":"","image":{"@type":"ImageObject","url":""},"articleSection":"Uncategorised","author":[{"@type":"Person","name":"Vincenzo Zambianchi"}],"creator":["Vincenzo Zambianchi"],"publisher":{"@type":"Organization","name":"Simply Business UK","logo":"https:\/\/www.simplybusiness.co.uk\/wp-content\/uploads\/sites\/3\/2024\/04\/icon-512x512-1.png"},"keywords":[],"dateCreated":"2021-02-02T14:42:00Z","datePublished":"2021-02-02T14:42:00Z","dateModified":"2025-05-22T13:19:12Z"},"rendered":"<script type=\"application\/ld+json\" class=\"wp-parsely-metadata\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@type\":\"NewsArticle\",\"headline\":\"Go routines for stateless AWS Lambda functions\",\"url\":\"http:\\\/\\\/www.simplybusiness.co.uk\\\/about-us\\\/tech\\\/2021\\\/02\\\/go-routines-aws-lambda\",\"mainEntityOfPage\":{\"@type\":\"WebPage\",\"@id\":\"http:\\\/\\\/www.simplybusiness.co.uk\\\/about-us\\\/tech\\\/2021\\\/02\\\/go-routines-aws-lambda\"},\"thumbnailUrl\":\"\",\"image\":{\"@type\":\"ImageObject\",\"url\":\"\"},\"articleSection\":\"Uncategorised\",\"author\":[{\"@type\":\"Person\",\"name\":\"Vincenzo Zambianchi\"}],\"creator\":[\"Vincenzo Zambianchi\"],\"publisher\":{\"@type\":\"Organization\",\"name\":\"Simply Business UK\",\"logo\":\"https:\\\/\\\/www.simplybusiness.co.uk\\\/wp-content\\\/uploads\\\/sites\\\/3\\\/2024\\\/04\\\/icon-512x512-1.png\"},\"keywords\":[],\"dateCreated\":\"2021-02-02T14:42:00Z\",\"datePublished\":\"2021-02-02T14:42:00Z\",\"dateModified\":\"2025-05-22T13:19:12Z\"}<\/script>","tracker_url":"https:\/\/cdn.parsely.com\/keys\/simplybusiness.co.uk\/p.js"},"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/www.simplybusiness.co.uk\/wp-json\/wp\/v2\/posts\/342","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.simplybusiness.co.uk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.simplybusiness.co.uk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.simplybusiness.co.uk\/wp-json\/wp\/v2\/users\/14"}],"replies":[{"embeddable":true,"href":"https:\/\/www.simplybusiness.co.uk\/wp-json\/wp\/v2\/comments?post=342"}],"version-history":[{"count":27,"href":"https:\/\/www.simplybusiness.co.uk\/wp-json\/wp\/v2\/posts\/342\/revisions"}],"predecessor-version":[{"id":37864,"href":"https:\/\/www.simplybusiness.co.uk\/wp-json\/wp\/v2\/posts\/342\/revisions\/37864"}],"wp:attachment":[{"href":"https:\/\/www.simplybusiness.co.uk\/wp-json\/wp\/v2\/media?parent=342"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.simplybusiness.co.uk\/wp-json\/wp\/v2\/tags?post=342"},{"taxonomy":"hidden-category","embeddable":true,"href":"https:\/\/www.simplybusiness.co.uk\/wp-json\/wp\/v2\/hidden-category?post=342"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.simplybusiness.co.uk\/wp-json\/wp\/v2\/coauthors?post=342"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}