title: lambda@edge timeout and s3 image processing
body: <p>I use a lambda@edge function to resize images on the fly. this works quite well - except when calling this function f.e. 5x at the same time. then the lookup for the image on s3 takes ~4 seconds. since lambda@edge functions only have a max. timeout of 5s, I have only 1s left which is way too little to process an image.</p>
  
  <p><strong>So I was asking myself, why is the limit sooo low at 5s?</strong></p>
  
  <p>Maybe I can optimize the s3-lookup for the image which takes 4s when calling the function multiple times (when only calling it for 1 image, its really fast at 200ms).</p>
  
  <p>s3 lookup:</p>
  
  <pre class="lang-js prettyprint-override"><code>export async function s3ObjectExists(Key: string, Bucket = BucketFiles) {
      try {
          await s3HeadObject(Key, Bucket);
      } catch (e) {
          if (e &amp;&amp; e.code === 'NotFound') {
              return false;
          }
  
          throw new Error(e);
      }
  
      return true;
  }
  </code></pre>
  
  <p>whole code of the lambda@edge function (simplified): </p>
  
  <pre class="lang-js prettyprint-override"><code>exports.handler = async (e) =&gt; {
      const { request, response } = e.Records[0].cf;
      const q = getQuery(request.querystring);
      const { uri } = request;
  
      const match = uri.match(/^\/((.+)\.(png|jpg|jpeg))/i);
      const key = match[1];
      const keyWithoutExt = match[2];
      const keyExt = match[3] as 'jpg' | 'png';
      const ext = q.format === 'webp' ? 'webp' : keyExt.toLowerCase();
      const newKey = getKey(`${keyWithoutExt}${JSON.stringify(q)}.${keyExt}`);
  
      if (await s3ObjectExists(newKey, bucketTmp)) {
          const file = await s3GetObject(newKey, bucketTmp);
  
          response.body = file.Body.toString('base64');
      } else {
          const file = await s3GetObject(key, bucket);
  
          let sharpConfig = sharp(file.Body as Buffer);
  
          if (q.width || q.height) {
              sharpConfig = sharpConfig.resize(q.width, q.height, {
                  withoutEnlargement: true
              });
          }
  
          const buffer = await sharpConfig.toBuffer();
  
          await s3PutObject(bucketTmp, newKey, buffer, {
              CacheControl: 'max-age=31536000',
              Tagging: 'ImageCache=true'
          });
  
          response.body = buffer.toString('base64');
      }
  
      response.status = 200;
      response.bodyEncoding = 'base64';
      response.headers['content-type'] = [
          {
              key: 'Content-Type',
              value: 'image/' + ext === 'jpg' ? 'jpeg' : ext
          }
      ];
  
      return response;
  };
  </code></pre>