The aws:datasync/task:Task resource, part of the Pulumi AWS provider, defines a DataSync task configuration that specifies how files should be synchronized between two locations. This guide focuses on four capabilities: basic task creation, scheduled execution, file filtering, and enhanced mode for S3 transfers.
DataSync tasks connect pre-existing locations (S3, EFS, FSx, NFS, SMB). The task resource defines the sync configuration; actual file transfers happen when you execute the task outside of Pulumi. The examples are intentionally small. Combine them with your own DataSync locations and execution logic.
Create a basic task between two locations
Most deployments start by defining a task that connects a source to a destination. The task is a reusable configuration; you trigger actual transfers separately.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.datasync.Task("example", {
destinationLocationArn: destination.arn,
name: "example",
sourceLocationArn: source.arn,
options: {
bytesPerSecond: -1,
},
});
import pulumi
import pulumi_aws as aws
example = aws.datasync.Task("example",
destination_location_arn=destination["arn"],
name="example",
source_location_arn=source["arn"],
options={
"bytes_per_second": -1,
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/datasync"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := datasync.NewTask(ctx, "example", &datasync.TaskArgs{
DestinationLocationArn: pulumi.Any(destination.Arn),
Name: pulumi.String("example"),
SourceLocationArn: pulumi.Any(source.Arn),
Options: &datasync.TaskOptionsArgs{
BytesPerSecond: pulumi.Int(-1),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.DataSync.Task("example", new()
{
DestinationLocationArn = destination.Arn,
Name = "example",
SourceLocationArn = source.Arn,
Options = new Aws.DataSync.Inputs.TaskOptionsArgs
{
BytesPerSecond = -1,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.datasync.Task;
import com.pulumi.aws.datasync.TaskArgs;
import com.pulumi.aws.datasync.inputs.TaskOptionsArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Task("example", TaskArgs.builder()
.destinationLocationArn(destination.arn())
.name("example")
.sourceLocationArn(source.arn())
.options(TaskOptionsArgs.builder()
.bytesPerSecond(-1)
.build())
.build());
}
}
resources:
example:
type: aws:datasync:Task
properties:
destinationLocationArn: ${destination.arn}
name: example
sourceLocationArn: ${source.arn}
options:
bytesPerSecond: -1
The sourceLocationArn and destinationLocationArn link the task to existing DataSync locations. The options block controls transfer behavior; setting bytesPerSecond to -1 removes bandwidth limits. The task doesn’t transfer files until you execute it through the AWS console, CLI, or SDK.
Schedule automatic transfers with cron expressions
Teams running regular migrations or backups configure tasks to run automatically rather than triggering each execution manually.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.datasync.Task("example", {
destinationLocationArn: destination.arn,
name: "example",
sourceLocationArn: source.arn,
schedule: {
scheduleExpression: "cron(0 12 ? * SUN,WED *)",
},
});
import pulumi
import pulumi_aws as aws
example = aws.datasync.Task("example",
destination_location_arn=destination["arn"],
name="example",
source_location_arn=source["arn"],
schedule={
"schedule_expression": "cron(0 12 ? * SUN,WED *)",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/datasync"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := datasync.NewTask(ctx, "example", &datasync.TaskArgs{
DestinationLocationArn: pulumi.Any(destination.Arn),
Name: pulumi.String("example"),
SourceLocationArn: pulumi.Any(source.Arn),
Schedule: &datasync.TaskScheduleArgs{
ScheduleExpression: pulumi.String("cron(0 12 ? * SUN,WED *)"),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.DataSync.Task("example", new()
{
DestinationLocationArn = destination.Arn,
Name = "example",
SourceLocationArn = source.Arn,
Schedule = new Aws.DataSync.Inputs.TaskScheduleArgs
{
ScheduleExpression = "cron(0 12 ? * SUN,WED *)",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.datasync.Task;
import com.pulumi.aws.datasync.TaskArgs;
import com.pulumi.aws.datasync.inputs.TaskScheduleArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Task("example", TaskArgs.builder()
.destinationLocationArn(destination.arn())
.name("example")
.sourceLocationArn(source.arn())
.schedule(TaskScheduleArgs.builder()
.scheduleExpression("cron(0 12 ? * SUN,WED *)")
.build())
.build());
}
}
resources:
example:
type: aws:datasync:Task
properties:
destinationLocationArn: ${destination.arn}
name: example
sourceLocationArn: ${source.arn}
schedule:
scheduleExpression: cron(0 12 ? * SUN,WED *)
The schedule block defines when DataSync executes the task. The scheduleExpression uses cron syntax; this example runs every Sunday and Wednesday at noon UTC. DataSync handles execution automatically once the schedule is active.
Filter files with include and exclude patterns
Large datasets often contain files that shouldn’t be transferred. Pattern-based filtering controls which files participate in the sync.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.datasync.Task("example", {
destinationLocationArn: destination.arn,
name: "example",
sourceLocationArn: source.arn,
excludes: {
filterType: "SIMPLE_PATTERN",
value: "/folder1|/folder2",
},
includes: {
filterType: "SIMPLE_PATTERN",
value: "/folder1|/folder2",
},
});
import pulumi
import pulumi_aws as aws
example = aws.datasync.Task("example",
destination_location_arn=destination["arn"],
name="example",
source_location_arn=source["arn"],
excludes={
"filter_type": "SIMPLE_PATTERN",
"value": "/folder1|/folder2",
},
includes={
"filter_type": "SIMPLE_PATTERN",
"value": "/folder1|/folder2",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/datasync"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := datasync.NewTask(ctx, "example", &datasync.TaskArgs{
DestinationLocationArn: pulumi.Any(destination.Arn),
Name: pulumi.String("example"),
SourceLocationArn: pulumi.Any(source.Arn),
Excludes: &datasync.TaskExcludesArgs{
FilterType: pulumi.String("SIMPLE_PATTERN"),
Value: pulumi.String("/folder1|/folder2"),
},
Includes: &datasync.TaskIncludesArgs{
FilterType: pulumi.String("SIMPLE_PATTERN"),
Value: pulumi.String("/folder1|/folder2"),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.DataSync.Task("example", new()
{
DestinationLocationArn = destination.Arn,
Name = "example",
SourceLocationArn = source.Arn,
Excludes = new Aws.DataSync.Inputs.TaskExcludesArgs
{
FilterType = "SIMPLE_PATTERN",
Value = "/folder1|/folder2",
},
Includes = new Aws.DataSync.Inputs.TaskIncludesArgs
{
FilterType = "SIMPLE_PATTERN",
Value = "/folder1|/folder2",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.datasync.Task;
import com.pulumi.aws.datasync.TaskArgs;
import com.pulumi.aws.datasync.inputs.TaskExcludesArgs;
import com.pulumi.aws.datasync.inputs.TaskIncludesArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Task("example", TaskArgs.builder()
.destinationLocationArn(destination.arn())
.name("example")
.sourceLocationArn(source.arn())
.excludes(TaskExcludesArgs.builder()
.filterType("SIMPLE_PATTERN")
.value("/folder1|/folder2")
.build())
.includes(TaskIncludesArgs.builder()
.filterType("SIMPLE_PATTERN")
.value("/folder1|/folder2")
.build())
.build());
}
}
resources:
example:
type: aws:datasync:Task
properties:
destinationLocationArn: ${destination.arn}
name: example
sourceLocationArn: ${source.arn}
excludes:
filterType: SIMPLE_PATTERN
value: /folder1|/folder2
includes:
filterType: SIMPLE_PATTERN
value: /folder1|/folder2
The excludes and includes blocks use SIMPLE_PATTERN filtering. The value property accepts pipe-separated patterns; this example includes or excludes specific folders. Filters apply during task execution, reducing transfer time and costs.
Use enhanced mode for S3-to-S3 transfers
S3-to-S3 transfers can use enhanced mode for higher performance and more detailed metrics.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.datasync.Task("example", {
destinationLocationArn: destination.arn,
name: "example",
sourceLocationArn: source.arn,
taskMode: "ENHANCED",
options: {
gid: "NONE",
posixPermissions: "NONE",
uid: "NONE",
verifyMode: "ONLY_FILES_TRANSFERRED",
},
});
import pulumi
import pulumi_aws as aws
example = aws.datasync.Task("example",
destination_location_arn=destination["arn"],
name="example",
source_location_arn=source["arn"],
task_mode="ENHANCED",
options={
"gid": "NONE",
"posix_permissions": "NONE",
"uid": "NONE",
"verify_mode": "ONLY_FILES_TRANSFERRED",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/datasync"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := datasync.NewTask(ctx, "example", &datasync.TaskArgs{
DestinationLocationArn: pulumi.Any(destination.Arn),
Name: pulumi.String("example"),
SourceLocationArn: pulumi.Any(source.Arn),
TaskMode: pulumi.String("ENHANCED"),
Options: &datasync.TaskOptionsArgs{
Gid: pulumi.String("NONE"),
PosixPermissions: pulumi.String("NONE"),
Uid: pulumi.String("NONE"),
VerifyMode: pulumi.String("ONLY_FILES_TRANSFERRED"),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.DataSync.Task("example", new()
{
DestinationLocationArn = destination.Arn,
Name = "example",
SourceLocationArn = source.Arn,
TaskMode = "ENHANCED",
Options = new Aws.DataSync.Inputs.TaskOptionsArgs
{
Gid = "NONE",
PosixPermissions = "NONE",
Uid = "NONE",
VerifyMode = "ONLY_FILES_TRANSFERRED",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.datasync.Task;
import com.pulumi.aws.datasync.TaskArgs;
import com.pulumi.aws.datasync.inputs.TaskOptionsArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Task("example", TaskArgs.builder()
.destinationLocationArn(destination.arn())
.name("example")
.sourceLocationArn(source.arn())
.taskMode("ENHANCED")
.options(TaskOptionsArgs.builder()
.gid("NONE")
.posixPermissions("NONE")
.uid("NONE")
.verifyMode("ONLY_FILES_TRANSFERRED")
.build())
.build());
}
}
resources:
example:
type: aws:datasync:Task
properties:
destinationLocationArn: ${destination.arn}
name: example
sourceLocationArn: ${source.arn}
taskMode: ENHANCED
options:
gid: NONE
posixPermissions: NONE
uid: NONE
verifyMode: ONLY_FILES_TRANSFERRED
The taskMode property switches to ENHANCED, which is only available for S3-to-S3 transfers. Enhanced mode requires specific options: setting gid, uid, and posixPermissions to NONE tells DataSync not to preserve Unix metadata. The verifyMode property controls data integrity checks; ONLY_FILES_TRANSFERRED verifies only newly transferred files.
Beyond these examples
These snippets focus on specific task-level features: task creation and location linking, scheduling and filtering, and enhanced mode for S3 transfers. They’re intentionally minimal rather than full data migration solutions.
The examples reference pre-existing infrastructure such as DataSync source and destination locations (S3, EFS, FSx, NFS, SMB). They focus on configuring the task rather than provisioning the locations it connects.
To keep things focused, common task patterns are omitted, including:
- CloudWatch Logs integration (cloudwatchLogGroupArn)
- Task execution reports (taskReportConfig)
- Bandwidth throttling beyond bytesPerSecond
- Advanced options (preserveDeletedFiles, overwriteMode, transferMode)
These omissions are intentional: the goal is to illustrate how each task feature is wired, not provide drop-in migration modules. See the DataSync Task resource reference for all available configuration options.
Let's configure AWS DataSync Tasks
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Task Execution & Lifecycle
destinationLocationArn, sourceLocationArn, and taskMode properties are immutable. You’ll need to recreate the task to change these values.Task Modes & Performance
bytesPerSecond to -1 in the options block to allow unlimited bandwidth.Scheduling & Filtering
schedule block with a scheduleExpression using cron syntax, such as cron(0 12 ? * SUN,WED *) for transfers at noon on Sundays and Wednesdays.includes and excludes blocks with filterType: "SIMPLE_PATTERN" and pipe-separated paths in the value field (e.g., "/folder1|/folder2").Configuration & Options
options block sets default behavior, but you can override these options when starting individual task executions.gid: "NONE", posixPermissions: "NONE", uid: "NONE", and verifyMode: "ONLY_FILES_TRANSFERRED" as recommended settings.