Deploys - Overview
There are two ways to deploy to the serverless platform, using either git for continuous deployment (our recommended approach), or file deploys. We also provide SFTP access, but this is primarily used for viewing, editing or transferring a small number of files.
Git Deploy Strategies
For git deploys, you can choose between two deployment strategies that determine how your code is deployed and stored:
| Strategy | Best For | Rollback | Storage | Method |
|---|---|---|---|---|
| Versioned | Production apps needing instant rollback | Instant (previous versions retained) | Higher (full copy per deploy) | Atomic |
| Live | Large codebases, frequent deploys | Requires redeploy | Lower (single directory with incremental updates) | Incremental |
Versioned Strategy (Default)
Versioned deploys are atomic. Each deployment creates a new, complete copy of your application in a versioned directory, think of it like a git checkout. A live symlink points to the active version, enabling instant rollback to any previous deployment. Files not tracked by git will not persist between deploys, unless they are in our persistent storage.
Live Strategy
Uses a single persistent deploy directory with incremental syncing. Each build output is compared to the previous one and only changed files are updated. Files not changed, added, or deleted in the build output will not be touched between deploys — including files modified directly on the live site via SFTP or a CMS. The live symlink structure is maintained, allowing zero-downtime switching between strategies. See How Live Deploys Work for a detailed breakdown.
Atomic Deploys
Atomic deploys mean your whole application is deployed each time, and the existing release stays separate. This ensures zero downtime, simple rollback, and consistent state. Atomic deploys apply to file deploys and git deploys using the versioned strategy.
If you are used to deploying files with SFTP, SSH or similar this is a bit different, with two key concepts to keep in mind:
- Your application files are downloaded and replaced entirely each deployment, giving you a clean slate.
- Any files written to your application directory during runtime (think uploads, cache, logs, built artifacts) will not be present on the next deployment, unless placed in persistent storage of some kind.
Persistent Storage
For some parts of your application you may need persistent storage. Some common uses cases are for storing generated images, caches, logs, or user submitted content.
That’s where the shared directory /mnt/data/website/shared comes in – it’s a directory that exists outside your application’s deployment directory and survives across all deploys. You can write whatever files you like here, and they will be available to all deploys now and in the future. You can also structure it’s contents however you like. Here’s a simplified example of how we use it for our own website:
We have three things we want to persist between deploys. User submitted form entries, our generated responsive images and some logging. In our build script we have the following:
#!/bin/bash
# create shared directories if they don't existmkdir -p /mnt/data/website/shared/formsmkdir -p /mnt/data/website/shared/img-cachemkdir -p /mnt/data/website/shared/logs
# remove existing public image directoryrm -rf public/img-cache
# create symlink to persistent storage so image paths workln -sf /mnt/data/website/shared/img-cache public/img-cache
echo "✓ Symlinks created successfully"This gives us the three folders we want to persist, and we have made only the image directory accessible in our public/ directory to ensure existing image paths work and are available to the browser. The other two directories are private, so there’s no symlink required. Instead in our site.php we tell the system that’s where to write logs and form entries to:
return [ 'image_manipulation' => [ 'cache' => true, 'cache_path' => storage_path('/mnt/data/website/img-cache'), ],
'disks' => [ 'forms' => [ 'driver' => 'local', 'root' => storage_path('/mnt/data/website/forms'), ], 'logs' => [ 'driver' => 'local', 'root' => storage_path('/mnt/shared/logs'), ], ],];With that done we end up with the folder structure below in persistent storage:
Directorymnt/website/shared/
Directoryforms/
- …
Directoryimg-cache/ » public/img-cache
- …
Directorylogs/
- …
These folders and any files they container will accessible by all future deploys, and our image directory can be served to the browser, ensuring we’re not having to generate new images each deploy.