New to Kestra?
Use blueprints to kickstart your first workflows.
Incrementally back up a Dropbox folder to Amazon S3 nightly with Kestra: list, filter, copy only changed files via a KV watermark, with retries and alerts.
Keep a durable, off-platform copy of a Dropbox folder in an Amazon S3 bucket with an automated nightly backup. This flow is incremental: each run lists the Dropbox folder, then downloads and uploads only the files that changed since the last successful run, tracked through a KV store watermark. That keeps Dropbox egress and S3 PUT costs proportional to what actually changed and stops the job slowing down as the folder grows, solving the problem of brittle, full-copy backup scripts that re-transfer everything every night and silently skip files when they fail. It pairs the Dropbox plugin with the AWS S3 plugin for a cross-cloud, schedule-driven disaster-recovery copy.
list_dropbox_files (io.kestra.plugin.dropbox.files.List) recursively lists entries under dropbox_folder, capped at the max_files input (default 1000) with fetchType: FETCH so the rows are available to downstream tasks.backup_each_file (io.kestra.plugin.core.flow.ForEach) iterates over outputs.list_dropbox_files.rows with a concurrencyLimit of 4.backup_if_changed (io.kestra.plugin.core.flow.If) keeps only entries whose type is file (a recursive listing also returns folders, which Download cannot fetch) and whose clientModified timestamp is newer than vars.watermark.download_from_dropbox (io.kestra.plugin.dropbox.files.Download) stages it into Kestra internal storage, then upload_to_s3 (io.kestra.plugin.aws.s3.Upload) writes it to s3_bucket under a key that mirrors the Dropbox path beneath s3_prefix using STANDARD storage class.update_watermark (io.kestra.plugin.core.kv.Set) records the run's start time to the DROPBOX_BACKUP_WATERMARK KV key, but only after every changed file uploaded, so a mid-run failure re-tries the same window next time.Schedule trigger (nightly_backup) fires the backup at 02:00 UTC daily, and an alert_failure error handler posts a Slack message if the run does not complete.Neither Dropbox nor S3 ships a scheduler that can list one cloud, conditionally copy to another, and track incremental state across runs. Kestra fills that gap: a declarative YAML flow with an event or Schedule trigger, built-in per-task retries, a ForEach for bounded parallelism, an If guard for change detection, a persistent KV watermark for incremental state, and full execution lineage and logs over every transferred file. The result is observable, restartable, and version-controlled, instead of a cron-driven shell script no one can debug.
s3:PutObject on the target prefix.DROPBOX_ACCESS_TOKEN: Dropbox API access token used to list and download files.AWS_ACCESS_KEY_ID and AWS_SECRET_KEY_ID: AWS credentials for the S3 upload. Prefer an IAM role or instance profile and omit static keys; if you must use keys, scope the policy to arn:aws:s3:::<bucket>/<prefix>/*.AWS_DEFAULT_REGION: AWS region of the destination S3 bucket, for example eu-west-1.SLACK_WEBHOOK: Slack incoming webhook URL used by the failure alert.Never hardcode any of these values.
DROPBOX_ACCESS_TOKEN, AWS_ACCESS_KEY_ID, AWS_SECRET_KEY_ID, AWS_DEFAULT_REGION, and SLACK_WEBHOOK secrets to your namespace.dropbox_folder, s3_bucket, s3_prefix, and max_files inputs.STANDARD_IA or GLACIER after N days.Schedule trigger for a higher frequency, or trigger the flow from an upstream event.max_files.