Cross-cloud applications using shared IP addresses

Best practices for setting up cross-cloud applications using shared IP addresses to ensure your traffic remains trusted.

Ask about this Page
Copy for LLM
View as Markdown

Connectivity challenges with shared IP addresses

If you deploy services on serverless platforms like AWS Lambda or Google Cloud Functions, your outbound traffic typically uses a shared pool of public IP addresses. Because thousands of tenants share these ranges, a single user's activity can negatively affect the IP reputation. If a security provider blocks a shared range, your connection to the API might fail.

In addition, cloud providers may assess the geo-location based on the user's origin. In these cases, IP addresses from embargoed countries may be blocked by the cloud provider beyond the control of commercetools.

To ensure consistent connectivity, use one of the following methods:

Static outbound IP egress control

The most robust way to prevent blocking is to ensure your serverless functions always use a dedicated, static elastic IP (AWS) or reserved external IP (GCP) that you own and control.

AWS implementation (Lambda)

By default, Lambda runs in an AWS-managed VPC with public IPs. To fix this:

  • VPC integration: Move your Lambda into a private subnet within your own VPC.
  • NAT gateway: Route the private subnet's outbound traffic (0.0.0.0/0) through a NAT gateway located in a public subnet.
  • Elastic IP: Associate a dedicated elastic IP with that NAT gateway.
Result: Every request to commercetools will originate from that single, static IP. You can then provide this IP to commercetools support or add it to your own allowlists.

GCP implementation (Cloud Functions and Cloud Run)

  • Serverless VPC access: Create a VPC Connector to link your serverless service to your VPC.
  • Cloud NAT: Create a Cloud Router and a Cloud NAT gateway.
  • Static IP assignment: Configure the Cloud NAT to use a manual IP allocation and assign a reserved static external IP.
  • Egress setting: Set the function egress setting to all-traffic to ensure all external calls, not only internal VPC calls, go through the NAT.

Private connectivity

For commercetools specifically, you can bypass the public internet entirely.

If you are hosted on GCP, commercetools offers Private Service Connect (PSC). This allows your VPC to connect to commercetools via a private IP address that never traverses the public internet, effectively making IP reputation a non-issue.

If you are on AWS, check with your Customer Success Manager regarding the availability of PrivateLink for your specific region, which functions similarly to PSC for AWS environments.

Client-side retry and rotation

If you cannot change the infrastructure, you can implement these client-side patterns:

  • Declare a global variable (for example, IS_IP_VERIFIED) to track the status.
  • If you detect a 403 Forbidden or a connection timeout that indicates an IP block: exit immediately.
    Since serverless containers are reused, you may want to force a cold start by changing the global variable programmatically, which often triggers the allocation of a new underlying host or IP address.
  • If the application returns 500 (GCP) or 502 Bad Gateway (AWS), let the client retry automatically.
    Implement exponential backoff with jitter on the client. Since the Lambda instance was terminated by your code (for example, by exiting the process), the cloud provider will be forced to provision a new instance for the retry, which will ideally land on an unblocked IP address.
Example Lambda with Canary test
import { exit } from 'process';

// --- CONFIGURATION ---
const TARGET_URL = 'https://api.europe-west1.gcp.commercetools.com/';

// Global variable acts as a "State Cache" to ensure we only test once per worker
let isIpVerified = false;

// Helper to get current IP (for logging only)
async function getCurrentIp() {
  try {
    const res = await fetch('https://checkip.amazonaws.com', { signal: AbortSignal.timeout(2000) });
    return (await res.text()).trim();
  } catch (error) {
    return "Unknown";
  }
}

async function runCanaryTest() {
  /**
   * Sends an OPTIONS request to the target.
   * Returns:
   * - true: If connection succeeds or error is NOT 403.
   * - false: ONLY if a 403 Forbidden is received.
   */
  try {
    const response = await fetch(TARGET_URL, {
      method: 'OPTIONS',
      headers: { 'User-Agent': 'AWS-Lambda-Canary-Check' },
      signal: AbortSignal.timeout(3000) // 3-second timeout
    });

    // CHECK: Only fail specifically on 403
    if (response.status === 403) {
      return false;
    }

    // Treat 200, 404, 500, etc., as "Safe" to avoid killing workers on server glitches
    return true;

  } catch (error) {
    // If connection completely fails (timeout/DNS), assume safe or fail open
    return true;
  }
}

export const handler = async (event) => {
  // 1. Warm Start Optimization (Skip check if already verified)
  if (isIpVerified) {
    return businessLogic(event);
  }

  // 2. Perform Canary Test (Cold Start Only)
  const isSafe = await runCanaryTest();

  // 3. Handle Failure (Only log if Bad IP is detected)
  if (!isSafe) {
    const currentIp = await getCurrentIp();
    console.log(`CRITICAL: Bad IP Detected (${currentIp}). Endpoint returned 403. Terminating Worker.`);

    // Kill the worker immediately to force a new IP on the client's retry
    exit(1);
  }

  // 4. Success Path (Silent)
  isIpVerified = true;
  return businessLogic(event);
};

function businessLogic(event) {
  return {
    statusCode: 200,
    body: JSON.stringify('Request processed successfully')
  };
}

Limitations and considerations

While currently very few IP addresses used by major cloud providers are blocked by cloud providers, you should log and monitor errors of this type to detect trends. Should the frequency of blocked IPs increase, consider moving to a static outbound IP solution.

Impact and summary

This approach will effectively filter out a small number of blocked IP addresses at negligible cost and with no performance impact on 99.9 percent of your traffic. Once the frequency begins to impede operations, raise a support ticket and share the blocked IP addresses so we can escalate them to our cloud provider.
While the canary test approach is free with no NAT gateway hourly charges, the static outbound IP approach is superior for enterprise applications because:
  • Deterministic success: You avoid unpredictable IP address changes.
  • No latency penalty: No extra HTTP calls during cold starts.

Comparison

ApproachComplexityReliability
Private connectivityHigherHighest (no public internet)
Static outbound IPMediumHigh (standard best practice)
Client-side Retry/RotationLowLow (reactive, not proactive)