Using Multiple Cloudfront Domains with Paperclip

In order to speed up asset loading using a CDN is generally regarded as a good idea. It is also recommended to split up requests among separate hostnames to allow the browser to parallelize loading.

Enabling this in Rails with Paperclip is pretty easy, though the documentation isn’t extremely rich.

You’ll want to set the s3_host_alias option to a proc which determines the correct domain alias based on the id of the object the attachment is for.

  has_attached_file :image, S3_OPTS.merge(
    :s3_host_alias => Proc.new {|attachment| "images#{attachment.instance.id % 4}.pixieengine.com" },
    :styles => {
      ...
    }
  )

This sends requests to the following hostnames:

images0.pixieengine.com
images1.pixieengine.com
images2.pixieengine.com
images3.pixieengine.com

The best part is that the same image will always have the same hostname. I’ve seen some people suggest randomly choosing a domain, but that reduces caching potential as the same item could be requested from multiple different domains over time.

Author: Daniel X

Heretic priest of the Machine God. I enjoy crawling around in Jeff Bezo's spaceship, bringing technology to the people, and long walks outside of time and space.

4 thoughts on “Using Multiple Cloudfront Domains with Paperclip”

  1. I found the given technique interfered w/ marshaling for Rails caching, causing an exception ‘no _dump_data is defined for class Proc’ deep in the cache serialization code.

    Instead, I patched the s3_host_alias method, which worked great:

    #
    # Override Paperclip to use multiple CNAMES to allow browsers to parallelize image asset loading
    #
    module Paperclip
    module Storage
    module S3
    # Override
    def s3_host_alias
    host_alias = @options[:s3_host_alias]
    host_alias.sub(‘%d’, (self.instance.id % 4).to_s)
    end
    end
    end
    end

    Like

    1. You’d want to be sure to map the same instance to the same number for better caching performance. If the last character in your ids is in the range 0-f you could parse it as a hex integer and % 4, that way the same instances will have the same caching domain.

      Like

  2. Wowowow… you have no idea how much I needed to find this post! Your implementation worked perfectly for my purposes. Although, I’m currently waiting on namecheap to recognize the other cnames I set up, but that’s a different issue altogether. One of them works, so now it’s just a waiting game. Thanks again!

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s