| title | Setting up PrivateLink in the AWS Console |
|---|---|
| sidebarTitle | AWS Console setup |
| description | Step-by-step guide for exposing a resource from your AWS account to Trigger.dev via PrivateLink. |
This guide walks through setting up the AWS side of a private connection: a Network Load Balancer (NLB), a target group pointing at the resource you want to expose, and a VPC Endpoint Service that authorizes Trigger.dev to consume it.
Prefer Terraform? Open the "Add connection" page in the Trigger.dev dashboard and use the Terraform wizard to generate a ready-to-apply script. The wizard creates everything described below and pre-fills our AWS account ID for you.Before you start you'll need:
- An AWS account with permission to create VPC, EC2, and ELB resources
- A resource in a VPC subnet that you want to expose (RDS instance, ElastiCache cluster, internal API, etc.)
- The Trigger.dev AWS account ID — find this on the "Add connection" page in your Trigger.dev dashboard, in the "I have my details" or "Step-by-step guide" cards
- A VPC that contains the resource, with at least one private subnet per Availability Zone you want to serve from
The target group is how the NLB will know where to forward traffic. AWS requires a target group when creating a load balancer, so we'll set this up first.
Go to **EC2 → Target Groups → Create target group**. - **IP addresses** for RDS, ElastiCache, or any resource you can reach by IP - **Instances** for EC2 instances you own - **Application Load Balancer** if your resource sits behind an ALBFor most database use cases, **IP addresses** is correct. NLBs don't support Lambda targets
directly — if you need to expose a Lambda, put it behind an ALB and use the ALB target type.


<Warning>
RDS and ElastiCache endpoints' IP addresses can change after failover or maintenance. For long-lived
connections, consider running a small Lambda or sidecar that periodically resolves the DNS name and
updates the target group, or use a [DNS-resolved](https://aws.amazon.com/blogs/networking-and-content-delivery/hostname-as-target-for-network-load-balancers/)
target if your setup supports it.
</Warning>
The NLB is what PrivateLink exposes to Trigger.dev. It must be internal (not internet-facing).
Go to **EC2 → Load Balancers → Create load balancer** and choose **Network Load Balancer**. - **Name**: something descriptive, e.g. `trigger-postgres-nlb` - **Scheme**: **Internal** - **IP address type**: IPv4

- **Protocol**: TCP
- **Port**: same as your target group port (5432 for Postgres, 6379 for Redis, etc.)
- **Default action**: forward to the target group you created in Step 1

This is the resource that PrivateLink consumers connect to.
Confirm the NLB from Step 2 is in the **Active** state before starting this step. It won't appear in the **Available load balancers** dropdown until it has finished provisioning. Go to **VPC → Endpoint services → Create endpoint service**. - **Name**: optional, but useful for identification, e.g. `trigger-postgres-endpoint` - **Load balancer type**: Network - **Available load balancers**: select the NLB you created - **Require acceptance for endpoint**: **No** (recommended)
<Note>
If you set "Require acceptance" to **Yes**, every connection request from Trigger.dev will
sit in a pending state until you manually approve it. Setting it to **No** lets connections
come up automatically once the principal is allow-listed.
</Note>
If your tasks and resource are in the same region, you can skip this — same-region access is
enabled by default.
<Note>
Cross-region PrivateLink adds AWS data-transfer cost and ~10–30ms of latency depending on the
region pair. Prefer same-region when possible.
</Note>
By default, no one can connect to your endpoint service. You need to explicitly allow Trigger.dev's AWS account.
Go to **VPC → Endpoint services**, select the service you just created. Click the **Allow principals** tab, then **Allow principals**. Paste the principal ARN in this format, replacing `` with the Trigger.dev AWS account ID shown in your dashboard:```text
arn:aws:iam::<account-id>:root
```

<Warning>
You will find the correct AWS account ID in the **Add connection** page of the Trigger.dev
dashboard. Do not assume an account ID — it differs between Trigger.dev environments.
</Warning>

- **Friendly name**: a short, human-readable label for this connection.
- **VPC Endpoint Service name**: paste the `com.amazonaws.vpce.<region>.vpce-svc-...` value from Step 4.
- **Target region**: the AWS region your endpoint service lives in.
See the dedicated Troubleshooting page for common problems such as the "Private link not found" wizard error. A few quick checks specific to this setup flow:
- Confirm Trigger.dev's AWS account ID is in your endpoint service's **Allow principals** list. - Confirm the endpoint service is **Available** in the AWS console. - Confirm "Require acceptance" is set to **No** on the endpoint service. If it's set to **Yes**, the request is sitting in your pending queue and you must approve it manually. - Confirm the NLB has a target registered and the target's health check is passing. - Confirm the listener port matches the port your task code is dialing. - Confirm the security group on your resource allows inbound traffic from the NLB or the VPC's private IP range. - Try connecting from inside the VPC first (e.g., a bastion host) to rule out resource-side issues. - Cross-region connections add ~10–30ms RTT depending on the regions involved. If your tasks run in a different region than your resource, expect higher latency. - The NLB and target group's health checks influence connection setup time. Tighter health check intervals reduce failover time after a backend goes unhealthy. Delete the connection from **Organization Settings → Private Connections** in the Trigger.dev dashboard. We'll tear down our VPC Endpoint and remove the network policy automatically. You can then delete your VPC Endpoint Service, NLB, and target group on the AWS side.