info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
as part of the controller `create` action. Which controller is responsible depends on the kind of file uploaded.
A Rails controller upload is very similar to uploading to local storage. The main difference: Rails must
send an HTTP request to the object store. This happens via the [CarrierWave Fog](https://github.com/carrierwaveuploader/carrierwave#fog)
uploader.
As with local storage, this strategy benefits from [Workhorse assistance](#workhorse-assisted-uploads) to
keep some of the costly I/O work out of Ruby and Rails. Direct upload does a better job at this because it also keeps the HTTP PUT requests to object storage outside Puma.
This strategy is only suitable for small file uploads, as it is subject to Puma's 60 second request timeout.
### Direct upload
Direct upload is the recommended way to move large files into object storage in CNG installations like GitLab SaaS.
With direct upload enabled, Workhorse:
1. Authorizes the request with Rails.
1. Establishes a connection with the object store itself to transfer the file to a temporary location.
1. When the transfer is complete, Workhorse finalizes the request with Rails. Rails issues an object store copy operation to put the file in its final location.
1. Completes the upload by deleting the temporary file in object storage.
This strategy is a different form of [Workhorse assistance](#workhorse-assisted-uploads). It does not rely on shared storage that is accessible by both Workhorse and Puma.
Of all existing upload strategies, direct upload is best able to handle large (gigabyte) uploads. However, because Puma still does an object storage copy operation, which takes time proportional to the size of the upload, there remains a possibility of hitting Puma timeouts.
## Workhorse assisted uploads
Most uploads receive assistance from Workhorse in some way.
- Often, Workhorse buffers the upload to a temporary file. Workhorse adds metadata to the request to tell
Puma the name and location of the temporary file. This requires shared temporary storage between Workhorse and Puma.
All GitLab installations (including CNG) have this shared temporary storage.
- Workhorse sometimes pre-processes the file. For example, for CI artifact uploads, Workhorse creates a separate index
of the contents of the ZIP file. By doing this in Workhorse we bypass the Puma request timeout.
Compared to Sidekiq background processing, this has the advantage that the user does not see an intermediate state
where GitLab accepts the file but has not yet processed it.
- With direct upload, Workhorse can both pre-process the file and upload it to object storage.
Uploading a large file to object storage takes time; by doing this in Workhorse we avoid the Puma request timeout.