jeremylongshore

apollo-multi-env-setup

@jeremylongshore/apollo-multi-env-setup
jeremylongshore
1,004
123 forks
Updated 1/18/2026
View on GitHub

Configure Apollo.io multi-environment setup. Use when setting up development, staging, and production environments, or managing multiple Apollo configurations. Trigger with phrases like "apollo environments", "apollo staging", "apollo dev prod", "apollo multi-tenant", "apollo env config".

Installation

$skills install @jeremylongshore/apollo-multi-env-setup
Claude Code
Cursor
Copilot
Codex
Antigravity

Details

Pathplugins/saas-packs/apollo-pack/skills/apollo-multi-env-setup/SKILL.md
Branchmain
Scoped Name@jeremylongshore/apollo-multi-env-setup

Usage

After installing, this skill will be available to your AI coding assistant.

Verify installation:

skills list

Skill Instructions


name: apollo-multi-env-setup description: | Configure Apollo.io multi-environment setup. Use when setting up development, staging, and production environments, or managing multiple Apollo configurations. Trigger with phrases like "apollo environments", "apollo staging", "apollo dev prod", "apollo multi-tenant", "apollo env config". allowed-tools: Read, Write, Edit, Bash(kubectl:), Bash(curl:) version: 1.0.0 license: MIT author: Jeremy Longshore jeremy@intentsolutions.io

Apollo Multi-Environment Setup

Overview

Configure Apollo.io for multiple environments (development, staging, production) with proper isolation, configuration management, and deployment strategies.

Environment Strategy

EnvironmentPurposeAPI KeyRate LimitData Access
DevelopmentLocal devDev/SandboxLow (10/min)Test data only
StagingPre-prod testingStaging keyMedium (50/min)Limited prod
ProductionLive systemProduction keyFull (100/min)Full access

Configuration Structure

// src/config/apollo/environments.ts
import { z } from 'zod';

const EnvironmentConfigSchema = z.object({
  apiKey: z.string().min(1),
  baseUrl: z.string().url().default('https://api.apollo.io/v1'),
  rateLimit: z.number().positive(),
  timeout: z.number().positive().default(30000),
  cacheEnabled: z.boolean().default(true),
  cacheTtl: z.number().positive().default(300),
  features: z.object({
    search: z.boolean().default(true),
    enrichment: z.boolean().default(true),
    sequences: z.boolean().default(false),
    webhooks: z.boolean().default(false),
  }),
  logging: z.object({
    level: z.enum(['debug', 'info', 'warn', 'error']),
    redactPII: z.boolean().default(true),
  }),
});

type EnvironmentConfig = z.infer<typeof EnvironmentConfigSchema>;

const configs: Record<string, EnvironmentConfig> = {
  development: {
    apiKey: process.env.APOLLO_API_KEY_DEV || '',
    baseUrl: 'https://api.apollo.io/v1',
    rateLimit: 10,
    timeout: 30000,
    cacheEnabled: true,
    cacheTtl: 60, // Short cache in dev
    features: {
      search: true,
      enrichment: true,
      sequences: false, // Disabled in dev
      webhooks: false,
    },
    logging: {
      level: 'debug',
      redactPII: false, // Show full data in dev
    },
  },

  staging: {
    apiKey: process.env.APOLLO_API_KEY_STAGING || '',
    baseUrl: 'https://api.apollo.io/v1',
    rateLimit: 50,
    timeout: 30000,
    cacheEnabled: true,
    cacheTtl: 300,
    features: {
      search: true,
      enrichment: true,
      sequences: true,
      webhooks: true,
    },
    logging: {
      level: 'info',
      redactPII: true,
    },
  },

  production: {
    apiKey: process.env.APOLLO_API_KEY || '',
    baseUrl: 'https://api.apollo.io/v1',
    rateLimit: 90, // Buffer below 100
    timeout: 30000,
    cacheEnabled: true,
    cacheTtl: 900, // 15 min in prod
    features: {
      search: true,
      enrichment: true,
      sequences: true,
      webhooks: true,
    },
    logging: {
      level: 'warn',
      redactPII: true,
    },
  },
};

export function getConfig(): EnvironmentConfig {
  const env = process.env.NODE_ENV || 'development';
  const config = configs[env];

  if (!config) {
    throw new Error(`Unknown environment: ${env}`);
  }

  // Validate configuration
  const result = EnvironmentConfigSchema.safeParse(config);
  if (!result.success) {
    throw new Error(`Invalid Apollo config for ${env}: ${result.error.message}`);
  }

  return result.data;
}

export function validateEnvironment(): void {
  const config = getConfig();

  if (!config.apiKey) {
    throw new Error('Apollo API key is required');
  }

  console.log(`Apollo configured for ${process.env.NODE_ENV || 'development'}`);
  console.log(`  Rate limit: ${config.rateLimit}/min`);
  console.log(`  Features: ${Object.entries(config.features).filter(([,v]) => v).map(([k]) => k).join(', ')}`);
}

Environment Files

# .env.development
NODE_ENV=development
APOLLO_API_KEY_DEV=your-dev-api-key
APOLLO_RATE_LIMIT=10
APOLLO_CACHE_TTL=60
APOLLO_LOG_LEVEL=debug

# .env.staging
NODE_ENV=staging
APOLLO_API_KEY_STAGING=your-staging-api-key
APOLLO_RATE_LIMIT=50
APOLLO_CACHE_TTL=300
APOLLO_LOG_LEVEL=info

# .env.production
NODE_ENV=production
APOLLO_API_KEY=your-prod-api-key
APOLLO_RATE_LIMIT=90
APOLLO_CACHE_TTL=900
APOLLO_LOG_LEVEL=warn

Kubernetes ConfigMaps

# k8s/configmaps/apollo-config-dev.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: apollo-config
  namespace: development
data:
  NODE_ENV: "development"
  APOLLO_RATE_LIMIT: "10"
  APOLLO_CACHE_TTL: "60"
  APOLLO_LOG_LEVEL: "debug"
  APOLLO_FEATURES_SEARCH: "true"
  APOLLO_FEATURES_ENRICHMENT: "true"
  APOLLO_FEATURES_SEQUENCES: "false"
  APOLLO_FEATURES_WEBHOOKS: "false"
---
# k8s/configmaps/apollo-config-staging.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: apollo-config
  namespace: staging
data:
  NODE_ENV: "staging"
  APOLLO_RATE_LIMIT: "50"
  APOLLO_CACHE_TTL: "300"
  APOLLO_LOG_LEVEL: "info"
  APOLLO_FEATURES_SEARCH: "true"
  APOLLO_FEATURES_ENRICHMENT: "true"
  APOLLO_FEATURES_SEQUENCES: "true"
  APOLLO_FEATURES_WEBHOOKS: "true"
---
# k8s/configmaps/apollo-config-prod.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: apollo-config
  namespace: production
data:
  NODE_ENV: "production"
  APOLLO_RATE_LIMIT: "90"
  APOLLO_CACHE_TTL: "900"
  APOLLO_LOG_LEVEL: "warn"
  APOLLO_FEATURES_SEARCH: "true"
  APOLLO_FEATURES_ENRICHMENT: "true"
  APOLLO_FEATURES_SEQUENCES: "true"
  APOLLO_FEATURES_WEBHOOKS: "true"

Secrets Management

# k8s/secrets/apollo-secrets.yaml (use sealed-secrets in practice)
apiVersion: v1
kind: Secret
metadata:
  name: apollo-secrets
  namespace: ${NAMESPACE}
type: Opaque
stringData:
  api-key: ${APOLLO_API_KEY}
  webhook-secret: ${APOLLO_WEBHOOK_SECRET}
# Using External Secrets Operator
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: apollo-secrets
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: gcp-secret-manager
    kind: ClusterSecretStore
  target:
    name: apollo-secrets
  data:
    - secretKey: api-key
      remoteRef:
        key: apollo-api-key-${ENV}
    - secretKey: webhook-secret
      remoteRef:
        key: apollo-webhook-secret-${ENV}

Environment-Aware Client

// src/lib/apollo/env-client.ts
import { getConfig } from '../../config/apollo/environments';

class EnvironmentAwareApolloClient {
  private config = getConfig();

  async request<T>(options: RequestOptions): Promise<T> {
    // Check feature flag
    if (!this.isFeatureEnabled(options.feature)) {
      throw new Error(`Feature ${options.feature} is disabled in ${process.env.NODE_ENV}`);
    }

    // Apply environment-specific rate limiting
    await this.rateLimiter.acquire();

    // Make request with environment config
    const response = await axios({
      ...options,
      baseURL: this.config.baseUrl,
      timeout: this.config.timeout,
      params: {
        ...options.params,
        api_key: this.config.apiKey,
      },
    });

    // Log based on environment
    this.log('info', `Apollo ${options.method} ${options.url}`, {
      status: response.status,
      duration: response.headers['x-response-time'],
    });

    return response.data;
  }

  private isFeatureEnabled(feature: string): boolean {
    return this.config.features[feature as keyof typeof this.config.features] ?? true;
  }

  private log(level: string, message: string, meta?: object): void {
    if (this.shouldLog(level)) {
      const sanitized = this.config.logging.redactPII
        ? this.redactPII(meta)
        : meta;
      console[level as 'log'](`[Apollo] ${message}`, sanitized);
    }
  }

  private shouldLog(level: string): boolean {
    const levels = ['debug', 'info', 'warn', 'error'];
    return levels.indexOf(level) >= levels.indexOf(this.config.logging.level);
  }
}

Testing Across Environments

// tests/integration/env-tests.ts
describe('Environment Configuration', () => {
  const originalEnv = process.env.NODE_ENV;

  afterEach(() => {
    process.env.NODE_ENV = originalEnv;
  });

  it('loads development config correctly', () => {
    process.env.NODE_ENV = 'development';
    const config = getConfig();
    expect(config.rateLimit).toBe(10);
    expect(config.features.sequences).toBe(false);
  });

  it('loads staging config correctly', () => {
    process.env.NODE_ENV = 'staging';
    const config = getConfig();
    expect(config.rateLimit).toBe(50);
    expect(config.features.sequences).toBe(true);
  });

  it('loads production config correctly', () => {
    process.env.NODE_ENV = 'production';
    const config = getConfig();
    expect(config.rateLimit).toBe(90);
    expect(config.logging.redactPII).toBe(true);
  });

  it('throws on missing API key', () => {
    process.env.NODE_ENV = 'production';
    delete process.env.APOLLO_API_KEY;
    expect(() => validateEnvironment()).toThrow();
  });
});

Environment Promotion

#!/bin/bash
# scripts/promote-to-staging.sh

echo "Promoting to staging environment..."

# Verify staging key is configured
if [ -z "$APOLLO_API_KEY_STAGING" ]; then
  echo "Error: APOLLO_API_KEY_STAGING not set"
  exit 1
fi

# Run staging tests
NODE_ENV=staging npm run test:integration

# Deploy to staging
kubectl apply -f k8s/configmaps/apollo-config-staging.yaml
kubectl apply -f k8s/secrets/apollo-secrets-staging.yaml
kubectl rollout restart deployment/apollo-service -n staging

# Verify deployment
kubectl rollout status deployment/apollo-service -n staging
curl -sf https://staging.example.com/health/apollo || exit 1

echo "Successfully promoted to staging"

Output

  • Environment-specific configurations
  • Kubernetes ConfigMaps and Secrets
  • Environment-aware client
  • Feature flags per environment
  • Environment promotion scripts

Error Handling

IssueResolution
Wrong environmentCheck NODE_ENV variable
Missing API keyVerify secrets configuration
Feature disabledCheck environment config
Rate limit mismatchVerify config values

Resources

Next Steps

Proceed to apollo-observability for monitoring setup.

More by jeremylongshore

View all
rabbitmq-queue-setup
1,004

Rabbitmq Queue Setup - Auto-activating skill for Backend Development. Triggers on: rabbitmq queue setup, rabbitmq queue setup Part of the Backend Development skill category.

model-evaluation-suite
1,004

evaluating-machine-learning-models: This skill allows Claude to evaluate machine learning models using a comprehensive suite of metrics. It should be used when the user requests model performance analysis, validation, or testing. Claude can use this skill to assess model accuracy, precision, recall, F1-score, and other relevant metrics. Trigger this skill when the user mentions "evaluate model", "model performance", "testing metrics", "validation results", or requests a comprehensive "model evaluation".

neural-network-builder
1,004

building-neural-networks: This skill allows Claude to construct and configure neural network architectures using the neural-network-builder plugin. It should be used when the user requests the creation of a new neural network, modification of an existing one, or assistance with defining the layers, parameters, and training process. The skill is triggered by requests involving terms like "build a neural network," "define network architecture," "configure layers," or specific mentions of neural network types (e.g., "CNN," "RNN," "transformer").

oauth-callback-handler
1,004

Oauth Callback Handler - Auto-activating skill for API Integration. Triggers on: oauth callback handler, oauth callback handler Part of the API Integration skill category.