Skip to main content
AWS PrivateLink gives a colocated market maker a private connection from its own AWS VPC to Monaco’s gRPC trading API and WebSocket feeds. Traffic stays on the AWS network and never crosses the public internet or the Cloudflare edge, and order entry gets 4× the public order budgets.
PrivateLink is available on staging (testnet) today, in us-east-1. It is offered on request for a fixed monthly cost. Reach out to the Monaco team to get started.

What changes

What stays the same:
  • Authentication. The rules are the public hosts’ rules. Trading and account RPCs and the WebSocket Authenticate handshake are signed with your ed25519 session key; market data, public WebSocket channels, and health checks need no signature. PrivateLink is a network path, not an authentication boundary, so it relaxes none of this. See Wallets & Auth.
  • The API surface. Same gRPC services and methods, same WebSocket channels, events, and message limits.
  • Every other budget. Apart from the order and per-address budgets above, reads, movements, settings writes, WebSocket limits, and resting-order caps match the public path. See Rate Limits.

How it works

  • Admission. Only AWS accounts Monaco has allowlisted can create an endpoint to the service, and Monaco accepts each endpoint connection by hand. Past that, each call is authenticated exactly as on the public path.
  • The ingress is decided by the listener, not by you. A connection that arrives over PrivateLink is metered against the PrivateLink order budgets. You send nothing different, and nothing you send can change it. The x-ratelimit-* budget headers report the PrivateLink figures. PrivateLink and public order budgets are separate buckets, and the family budget applies to each at 4×.
  • TLS. TLS terminates at Monaco’s load balancer with the public *.apimonaco.xyz certificate, so standard WebPKI roots verify it, provided your client verifies against pl-staging.apimonaco.xyz. The :443 listener offers HTTP/2 only (ALPN h2), which every standard gRPC client negotiates. The :8443 listener accepts the HTTP/1.1 upgrade WebSocket needs. Plaintext is not accepted on either port.
  • One Availability Zone. The service runs in a single Availability Zone, the same one as the Monaco API services behind it, and your endpoint must sit in that zone too, so traffic never crosses an AZ boundary. An outage of that AZ takes down the public hosts as well, so they are no fallback for it. They are a fallback for any failure confined to the PrivateLink path: on your side, such as your endpoint, its security group, or your DNS resolution, and on Monaco’s side, such as the endpoint service, its load balancer, or a listener, while the API services behind it stay up.
  • One region. An interface endpoint can only reach a service in its own region. Staging is in us-east-1.
  • Deploys. When Monaco rolls API tasks, connections on a draining task are reset after 30 seconds. Reconnect with backoff and resync, exactly as on the public path. See Reconnect and resync.

Set up

You need an AWS account with a VPC in us-east-1. For private DNS, the VPC must have both enableDnsSupport and enableDnsHostnames turned on.
1

Request access

Send the Monaco team the AWS principal that will create the endpoint: your account root (arn:aws:iam::<account-id>:root) or a specific IAM role ARN.Once Monaco has allowlisted it, you receive:
  • the endpoint service name, com.amazonaws.vpce.us-east-1.vpce-svc-…
  • the Availability Zone ID the service runs in, for example use1-az4
2

Pick a subnet in that AZ ID

Match on the AZ ID, never the AZ name. AZ names such as us-east-1a map to different physical zones in different AWS accounts.
If none comes back, create a subnet in that AZ ID first.
3

Create a security group for the endpoint

Allow inbound TCP 443 (gRPC) and 8443 (WebSocket feeds) from your trading hosts.
4

Create the interface endpoint

The endpoint starts in pendingAcceptance. Private DNS is enabled in a later step, once the connection is accepted.
5

Send Monaco the endpoint ID

Send the vpce-… ID from the previous step. Once Monaco accepts the connection, the endpoint state becomes available:
6

Enable private DNS

Inside your VPC, and only there, pl-staging.apimonaco.xyz now resolves to your endpoint’s private addresses. The hostname has no public DNS record, so outside a VPC with private DNS on it does not resolve at all.The change takes several minutes to reach your VPC’s resolver: in Monaco’s own test it took about seven minutes before the hostname resolved. Connections through a newly accepted endpoint can also time out for the first few minutes. Wait and retry before troubleshooting.
7

Verify

From a trading host:
grpc_health_probe calls the standard grpc.health.v1.Health/Check service and should print status: SERVING.

Connect

gRPC

Point your channel at https://pl-staging.apimonaco.xyz and turn on HTTP/2 keepalive. The load balancer drops a connection that stays idle for 350 seconds, and the server sends no keepalive of its own, so a quiet channel can be dropped without warning and fail its next call. A ping every 30 seconds keeps it open. With the Rust gRPC SDK:
Everything else, including request signing and idempotency keys, is unchanged from Authenticate requests.

WebSocket feeds

Connect to wss://pl-staging.apimonaco.xyz:8443/ws. The server sends a heartbeat every 25 seconds, so the idle timeout never applies to a healthy connection. With the TypeScript SDK, override only the WebSocket URL. REST calls keep using the public host:
The TypeScript SDK places orders over REST, which is not offered over PrivateLink. To get the PrivateLink order budgets, send orders over gRPC.

Without private DNS

This fallback is for gRPC. WebSocket feeds need private DNS, or a WebSocket client that sets the TLS server name separately from the URL. The TypeScript SDK’s client can’t, so with it, connecting to the endpoint DNS name always fails certificate verification. If you can’t enable private DNS, connect your gRPC channel to the endpoint’s own DNS name, vpce-….vpce-svc-….us-east-1.vpce.amazonaws.com (shown under DnsEntries in describe-vpc-endpoints), and set the TLS server name to pl-staging.apimonaco.xyz. The certificate does not cover the endpoint name, so verification fails without that override. Don’t turn off certificate or hostname verification to get past the mismatch; set the server name instead.

Troubleshooting

Offboarding

Tell the Monaco team. Monaco removes your principal from the allowlist and rejects the endpoint connection. Then delete your endpoint:

Rate Limits

Public and PrivateLink order budgets, budget headers, and backoff.

Market-Maker Runbook

Quote lifecycle, state tracking, reconnect, and emergency stop.

Rust gRPC SDK

Connect, sign requests, and place orders over gRPC.

WebSocket Reference

Channels, events, heartbeats, and close codes.