Skip to content

Slow Cloudfront images

0

Hello there!

We create Cloudfront distributions through the CDK, we got alert that "'CloudFrontWebDistribution' is deprecated" so I created new distributions with "Distribution", I create an S3 bucket, OAC policy and cache policy. The old distribution uses OAI and legacy caching (with the same settings as the cache policy).

The problem I have is that the new distributions, especially images are extremely slow, the old distribution loads an image in 13-30ms and the new distributions 300ms-1.2seconds, BUT not always.

What I have tried -

  1. Manually set the new distribution to use legacy caching to no success.
  2. Created an Origin Request Policy with settings Headers-None, Cookies-None and Quesry Strings-All
  3. Set the permissions on the bucket to the same as the old bucket
  4. I have set caching to 7 days from 1 day.

I have tested the response headers and whether it is a x-cache:Miss from cloudfront or x-cache: Hit from cloudfront it is still slow.

		let originAccessIdentity = new cloudfront.OriginAccessIdentity(this, name("oai"), {
			comment: id
		});
		const oldsiteBucket = new s3.Bucket(this, name("web-bucket"), {
			bucketName: name("web-bucket"),
			websiteIndexDocument: "index.html",
			websiteErrorDocument: "error.html",
			removalPolicy: isProd ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY
		});
		oldsiteBucket.grantRead(originAccessIdentity);

		let alternateSiteSubDomains = (buildProps.Params.LProviders as LProvider[]).filter(x => x.SiteSubDomain).map(x => x.SiteSubDomain + ".example.com");
		let tmpAlternateSiteSubDomains = (buildProps.Params.tmpLProviders as ILProvider[])
			.filter(x => x.SiteSubDomain)
			.map(x => x.SiteSubDomain + ".example.com");

		new cloudfront.CloudFrontWebDistribution(this, name("web-dist"), {
			comment: name("web-dist"),
			originConfigs: [
				{
					s3OriginSource: {
						s3BucketSource: oldsiteBucket,
						originAccessIdentity: originAccessIdentity
					},
					behaviors: [
						{
							isDefaultBehavior: true,
							defaultTtl: cdk.Duration.seconds(86400),
							maxTtl: cdk.Duration.seconds(86400),
							minTtl: cdk.Duration.seconds(86400),
							compress: true,
							forwardedValues: {
								queryString: true
							}
						}
					]
				}
			],
			httpVersion: cloudfront.HttpVersion.HTTP2_AND_3,
			viewerCertificate: cloudfront.ViewerCertificate.fromAcmCertificate(
				cert.Certificate.fromCertificateArn(this, name("eb-cert"), buildProps.Params.LWildcardCert),
				{
					aliases: [...new Set([buildProps.Params.SiteDomain, ...alternateSiteSubDomains])],
					securityPolicy: cloudfront.SecurityPolicyProtocol.TLS_V1_2_2021
				}
			),
			viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
			priceClass: PriceClass.PRICE_CLASS_ALL,
			errorConfigurations: [
				{
					errorCode: 404,
					errorCachingMinTtl: 300,
					responseCode: 200,
					responsePagePath: "/index.html"
				}
			]
		});

New distribution -

		// Create frontend web hosting S3 bucket
		const siteBucket = new s3.Bucket(this, name("website-bucket"), {
			bucketName: name("website-bucket"),
			websiteIndexDocument: "index.html",
			websiteErrorDocument: "error.html",
			removalPolicy: isProd ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY,
			publicReadAccess: true,
			blockPublicAccess: s3.BlockPublicAccess.BLOCK_ACLS
		});

		const distribution = new cloudfront.Distribution(this, name("dist"), {
			comment: name("dist"),
			defaultBehavior: {
				origin: origins.S3BucketOrigin.withOriginAccessControl(siteBucket),
				allowedMethods: cloudfront.AllowedMethods.ALLOW_GET_HEAD_OPTIONS,
				cachePolicy: new cloudfront.CachePolicy(this, name("CachePolicy"), {
					cachePolicyName: name("CachePolicy"),
					defaultTtl: cdk.Duration.seconds(86400),
					maxTtl: cdk.Duration.seconds(86400),
					minTtl: cdk.Duration.seconds(86400),
					queryStringBehavior: cloudfront.CacheQueryStringBehavior.all()
				}),
				compress: true,
				viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS
			},
			additionalBehaviors: {},
			defaultRootObject: "index.html",
			priceClass: cloudfront.PriceClass.PRICE_CLASS_ALL,
			httpVersion: cloudfront.HttpVersion.HTTP2_AND_3,
			minimumProtocolVersion: cloudfront.SecurityPolicyProtocol.TLS_V1_2_2021,
			certificate: cert.Certificate.fromCertificateArn(this, name("cf-cert"), buildProps.Params.LWildcardCert),
			domainNames: [...new Set([buildProps.Params.tmpSiteDomain, ...tmpAlternateSiteSubDomains])],
			errorResponses: [
				{
					httpStatus: 404,
					responseHttpStatus: 200,
					responsePagePath: "/index.html",
					ttl: cdk.Duration.seconds(300)
				}
			]
		});

		siteBucket.addToResourcePolicy(
			new iam.PolicyStatement({
				actions: ["s3:ListBucket"],
				resources: [siteBucket.bucketArn],
				principals: [new iam.ServicePrincipal("cloudfront.amazonaws.com")],
				conditions: {
					StringEquals: {
						"AWS:SourceArn": `arn:aws:cloudfront::${cdk.Aws.ACCOUNT_ID}:distribution/${distribution.distributionId}`
					}
				}
			})
		);

		siteBucket.addToResourcePolicy(
			new iam.PolicyStatement({
				actions: ["s3:GetObject"],
				resources: [`${siteBucket.bucketArn}/*`],
				principals: [new iam.ServicePrincipal("cloudfront.amazonaws.com")],
				conditions: {
					StringEquals: {
						"AWS:SourceArn": `arn:aws:cloudfront::${cdk.Aws.ACCOUNT_ID}:distribution/${distribution.distributionId}`
					}
				}
			})
		);
1 Answer
-1

The slow loading of images in your new CloudFront distribution could be caused by several factors. Here are some potential reasons and solutions to consider:

  1. Cache Hit Ratio: The new distribution may have a lower cache hit ratio compared to the old one. This can happen if the cache hasn't been sufficiently populated yet. Give it some time and monitor if performance improves as the cache builds up.

  2. Origin Shield: Consider enabling CloudFront Origin Shield. This additional caching layer can help reduce the load on your origin and improve overall performance, especially for less frequently accessed content.

  3. Compression: Ensure that compression is enabled for appropriate content types. While your configuration shows compression is enabled, double-check that it's working as expected.

  4. Origin Response Time: If your S3 bucket is in a different region from your users or CloudFront edge locations, it could lead to slower response times. Consider using CloudFront regional edge caches to help mitigate this.

  5. Cache Key: Review your cache key composition. Including all query strings might lead to unnecessary cache misses. Consider including only relevant query parameters in the cache key.

  6. TTL Settings: While you've set the TTL to 7 days, which should be sufficient, ensure that your origin is sending appropriate caching headers (Cache-Control, Expires) that align with your CloudFront TTL settings.

  7. Viewer Request Variations: Check if there are variations in viewer requests (e.g., different headers or cookies) that might be causing cache misses.

  8. Network Latency: Investigate if there are any network latency issues between CloudFront and your S3 bucket.

  9. Resource Optimization: Ensure your images are optimized for web delivery (appropriate format and compression).

  10. Logging and Monitoring: Enable CloudFront logging and use real-time logs to gain more insights into the caching behavior and identify the root cause of the slowdowns.

If the issue persists after addressing these points, you may need to conduct a more detailed analysis of your specific use case and potentially reach out to AWS support for further assistance.

Sources
Cloudfront caching issue | AWS re:Post
Cloudfront content download speed is too slow. | AWS re:Post
Caching and availability - Amazon CloudFront

answered 2 years ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.