> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fraudiant.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Best Practices

> Optimization strategies, performance tips, and recommended patterns for using Fraudiant effectively.

## Overview

Follow these best practices to maximize the value of Fraudiant while optimizing performance, cost, and user experience.

***

## Performance Optimization

### Implement Caching

<Warning>
  Caching validation results can reduce API calls by 70-90% and dramatically improve response times.
</Warning>

**Recommended caching strategy:**

```javascript theme={null}
const cache = new Map();
const CACHE_TTL = 24 * 60 * 60 * 1000; // 24 hours

async function validateEmailCached(email) {
  const cacheKey = email.toLowerCase();
  const cached = cache.get(cacheKey);

  // Check if cache exists and is not expired
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.data;
  }

  // Fetch from API
  const validation = await fetch(
    `https://api.fraudiant.com/email/${email}`,
    {
      headers: { 'Authorization': `Bearer ${process.env.FRAUDIANT_API_KEY}` }
    }
  ).then(r => r.json());

  // Store in cache
  cache.set(cacheKey, {
    data: validation,
    timestamp: Date.now()
  });

  return validation;
}
```

**Cache duration recommendations:**

* **Email validation**: 24-48 hours
* **Domain validation**: 48-72 hours (domains change less frequently)
* **Blocklist checks**: No caching (real-time updates needed)

### Use Redis for Distributed Caching

```javascript theme={null}
const redis = require('redis');
const client = redis.createClient();

async function validateWithRedis(email) {
  const cacheKey = `email_validation:${email.toLowerCase()}`;

  // Try cache first
  const cached = await client.get(cacheKey);
  if (cached) {
    return JSON.parse(cached);
  }

  // Call API
  const validation = await fetch(
    `https://api.fraudiant.com/email/${email}`,
    {
      headers: { 'Authorization': `Bearer ${process.env.FRAUDIANT_API_KEY}` }
    }
  ).then(r => r.json());

  // Cache for 24 hours
  await client.setEx(cacheKey, 86400, JSON.stringify(validation));

  return validation;
}
```

***

## Error Handling

### Fail Open Strategy

<Info>
  If the Fraudiant API is unavailable, allow users to proceed rather than blocking legitimate signups.
</Info>

```javascript theme={null}
async function validateEmailSafe(email) {
  try {
    const response = await fetch(
      `https://api.fraudiant.com/email/${email}`,
      {
        headers: { 'Authorization': `Bearer ${process.env.FRAUDIANT_API_KEY}` },
        timeout: 5000 // 5 second timeout
      }
    );

    if (!response.ok) {
      // Service error - fail open
      console.warn('Fraudiant service unavailable, allowing signup');
      return { valid: true, failedOpen: true };
    }

    const validation = await response.json();

    return {
      valid: !validation.disposable && !validation.spam && validation.mx,
      data: validation
    };

  } catch (error) {
    console.error('Email validation error:', error);
    // Fail open - don't block users due to service issues
    return { valid: true, failedOpen: true };
  }
}
```

### Implement Retry Logic with Exponential Backoff

```javascript theme={null}
async function validateWithRetry(email, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(
        `https://api.fraudiant.com/email/${email}`,
        {
          headers: { 'Authorization': `Bearer ${process.env.FRAUDIANT_API_KEY}` }
        }
      );

      if (response.status === 429) {
        // Rate limited - wait and retry
        const retryAfter = response.headers.get('Retry-After') || Math.pow(2, attempt);
        await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
        continue;
      }

      return await response.json();

    } catch (error) {
      if (attempt === maxRetries - 1) {
        // Last attempt failed - fail open
        return { disposable: false, spam: false, mx: true };
      }

      // Wait before retrying
      await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
    }
  }
}
```

***

## Rate Limit Management

### Monitor Rate Limit Headers

```javascript theme={null}
async function validateWithRateLimitCheck(email) {
  const response = await fetch(
    `https://api.fraudiant.com/email/${email}`,
    {
      headers: { 'Authorization': `Bearer ${process.env.FRAUDIANT_API_KEY}` }
    }
  );

  // Check rate limit headers
  const remaining = parseInt(response.headers.get('X-RateLimit-Remaining') || '0');
  const limit = parseInt(response.headers.get('X-RateLimit-Limit') || '0');
  const reset = parseInt(response.headers.get('X-RateLimit-Reset') || '0');

  // Warn if approaching limit
  if (remaining < limit * 0.1) {
    console.warn(`Approaching rate limit: ${remaining}/${limit} remaining`);
    // Consider implementing queue or backoff strategy
  }

  return response.json();
}
```

### Implement Request Queuing

```javascript theme={null}
class RateLimitedValidator {
  constructor(requestsPerSecond = 10) {
    this.queue = [];
    this.processing = false;
    this.interval = 1000 / requestsPerSecond;
  }

  async validate(email) {
    return new Promise((resolve, reject) => {
      this.queue.push({ email, resolve, reject });
      this.processQueue();
    });
  }

  async processQueue() {
    if (this.processing || this.queue.length === 0) return;

    this.processing = true;

    while (this.queue.length > 0) {
      const { email, resolve, reject } = this.queue.shift();

      try {
        const validation = await fetch(
          `https://api.fraudiant.com/email/${email}`,
          {
            headers: { 'Authorization': `Bearer ${process.env.FRAUDIANT_API_KEY}` }
          }
        ).then(r => r.json());

        resolve(validation);
      } catch (error) {
        reject(error);
      }

      // Wait before processing next request
      await new Promise(r => setTimeout(r, this.interval));
    }

    this.processing = false;
  }
}

// Usage
const validator = new RateLimitedValidator(10); // 10 requests per second
```

***

## Security Best Practices

### Protect API Keys

<Warning>
  Never expose API keys in client-side code, public repositories, or logs.
</Warning>

**DO:**

* Store keys in environment variables
* Use secret management systems (AWS Secrets Manager, HashiCorp Vault)
* Rotate keys regularly
* Use separate keys for each environment

**DON'T:**

* Hardcode keys in source code
* Commit keys to version control
* Share keys via email or chat
* Use production keys in development

### Validate Server-Side Only

```javascript theme={null}
// ❌ BAD: Client-side validation only
async function clientSideValidation(email) {
  // API key exposed in client code!
  const response = await fetch(`https://api.fraudiant.com/email/${email}`, {
    headers: { 'Authorization': 'Bearer YOUR_API_KEY' } // Never do this!
  });
  return response.json();
}

// ✅ GOOD: Server-side validation
// Frontend
async function validateEmail(email) {
  const response = await fetch('/api/validate', {
    method: 'POST',
    body: JSON.stringify({ email })
  });
  return response.json();
}

// Backend
app.post('/api/validate', async (req, res) => {
  const { email } = req.body;
  const validation = await fetch(
    `https://api.fraudiant.com/email/${email}`,
    {
      headers: { 'Authorization': `Bearer ${process.env.FRAUDIANT_API_KEY}` }
    }
  ).then(r => r.json());

  res.json({ valid: !validation.disposable && !validation.spam });
});
```

***

## User Experience

### Provide Clear Feedback

```javascript theme={null}
function getErrorMessage(validation) {
  if (validation.disposable) {
    return 'Temporary email addresses are not allowed. Please use a permanent email.';
  }

  if (validation.spam) {
    return 'This email domain is associated with spam. Please use a different email.';
  }

  if (!validation.mx) {
    return 'This email address cannot receive emails. Please check for typos.';
  }

  if (validation.did_you_mean) {
    return `Did you mean ${validation.did_you_mean}?`;
  }

  return 'Please provide a valid email address.';
}
```

### Implement Progressive Validation

```javascript theme={null}
// Validate as user types (with debouncing)
let validationTimeout;

function onEmailInput(email) {
  clearTimeout(validationTimeout);

  validationTimeout = setTimeout(async () => {
    const validation = await validateEmail(email);

    if (validation.did_you_mean) {
      showSuggestion(validation.did_you_mean);
    }

    if (!validation.valid) {
      showError(getErrorMessage(validation.data));
    } else {
      clearError();
    }
  }, 500); // Wait 500ms after user stops typing
}
```

### Handle Typos Gracefully

```javascript theme={null}
async function validateWithTypoCorrection(email) {
  const validation = await fetch(
    `https://api.fraudiant.com/email/${email}`,
    {
      headers: { 'Authorization': `Bearer ${process.env.FRAUDIANT_API_KEY}` }
    }
  ).then(r => r.json());

  if (validation.did_you_mean) {
    return {
      valid: true,
      suggestion: validation.did_you_mean,
      message: `Did you mean ${validation.did_you_mean}? Click to use this instead.`,
      autoCorrect: true
    };
  }

  return {
    valid: !validation.disposable && !validation.spam && validation.mx,
    data: validation
  };
}
```

***

## Cost Optimization

### Batch Validation

```javascript theme={null}
// Instead of validating each email immediately
async function processBulkEmails(emails) {
  // Deduplicate emails
  const uniqueEmails = [...new Set(emails.map(e => e.toLowerCase()))];

  // Check cache first
  const uncachedEmails = uniqueEmails.filter(email => !cache.has(email));

  // Validate only uncached emails with rate limiting
  const results = [];
  for (const email of uncachedEmails) {
    const validation = await validateEmail(email);
    cache.set(email, validation);
    results.push({ email, validation });

    // Rate limit: wait between requests
    await new Promise(r => setTimeout(r, 100)); // 10 requests per second
  }

  return results;
}
```

### Use Domain Validation for Pre-filtering

```javascript theme={null}
// Validate domain first (cheaper), then email if needed
async function efficientValidation(email) {
  const domain = email.split('@')[1];

  // Check domain first
  const domainValidation = await fetch(
    `https://api.fraudiant.com/domain/${domain}`,
    {
      headers: { 'Authorization': `Bearer ${process.env.FRAUDIANT_API_KEY}` }
    }
  ).then(r => r.json());

  // If domain is clearly bad, no need to validate full email
  if (domainValidation.disposable || domainValidation.spam || !domainValidation.mx) {
    return { valid: false, reason: 'Invalid domain' };
  }

  // Only validate full email if domain passed
  const emailValidation = await fetch(
    `https://api.fraudiant.com/email/${email}`,
    {
      headers: { 'Authorization': `Bearer ${process.env.FRAUDIANT_API_KEY}` }
    }
  ).then(r => r.json());

  return { valid: true, data: emailValidation };
}
```

***

## Testing

### Create Test Helpers

```javascript theme={null}
// Mock validator for testing
class MockEmailValidator {
  validate(email) {
    // Return fake validation for testing
    if (email.includes('disposable')) {
      return Promise.resolve({
        disposable: true,
        spam: false,
        mx: true
      });
    }

    return Promise.resolve({
      disposable: false,
      spam: false,
      mx: true
    });
  }
}

// Use in tests
describe('User Registration', () => {
  it('should reject disposable emails', async () => {
    const validator = new MockEmailValidator();
    const result = await validator.validate('[email protected]');
    expect(result.disposable).toBe(true);
  });
});
```

### Test with Different Environments

```javascript theme={null}
// config/fraudiant.js
module.exports = {
  development: {
    apiKey: process.env.FRAUDIANT_DEV_API_KEY,
    strictMode: false, // Allow more emails in dev
  },
  staging: {
    apiKey: process.env.FRAUDIANT_STAGING_API_KEY,
    strictMode: true,
  },
  production: {
    apiKey: process.env.FRAUDIANT_PROD_API_KEY,
    strictMode: true,
  }
};
```

***

## Monitoring & Observability

### Log Validation Results

```javascript theme={null}
async function validateWithLogging(email) {
  const startTime = Date.now();

  try {
    const validation = await fetch(
      `https://api.fraudiant.com/email/${email}`,
      {
        headers: { 'Authorization': `Bearer ${process.env.FRAUDIANT_API_KEY}` }
      }
    ).then(r => r.json());

    const duration = Date.now() - startTime;

    // Log metrics
    console.log({
      action: 'email_validation',
      email: email.split('@')[1], // Log domain only for privacy
      disposable: validation.disposable,
      spam: validation.spam,
      duration,
      timestamp: new Date().toISOString()
    });

    return validation;

  } catch (error) {
    console.error({
      action: 'email_validation_error',
      error: error.message,
      duration: Date.now() - startTime
    });

    throw error;
  }
}
```

### Track Rejection Rates

```javascript theme={null}
const metrics = {
  total: 0,
  rejected: 0,
  disposable: 0,
  spam: 0
};

async function validateWithMetrics(email) {
  metrics.total++;

  const validation = await validateEmail(email);

  if (validation.disposable) {
    metrics.rejected++;
    metrics.disposable++;
  }

  if (validation.spam) {
    metrics.rejected++;
    metrics.spam++;
  }

  // Log metrics periodically
  if (metrics.total % 100 === 0) {
    console.log({
      rejectionRate: (metrics.rejected / metrics.total * 100).toFixed(2) + '%',
      disposableRate: (metrics.disposable / metrics.total * 100).toFixed(2) + '%',
      spamRate: (metrics.spam / metrics.total * 100).toFixed(2) + '%'
    });
  }

  return validation;
}
```

***

## Summary

<CardGroup cols={2}>
  <Card title="Cache aggressively" icon="database">
    Reduce API calls by 70-90% with proper caching
  </Card>

  <Card title="Fail open gracefully" icon="shield-check">
    Don't block users when service is unavailable
  </Card>

  <Card title="Monitor rate limits" icon="gauge">
    Track usage and implement queuing strategies
  </Card>

  <Card title="Validate server-side" icon="lock">
    Never expose API keys in client code
  </Card>

  <Card title="Provide clear feedback" icon="message">
    Help users understand validation failures
  </Card>

  <Card title="Test thoroughly" icon="flask">
    Use separate environments and mock validators
  </Card>
</CardGroup>
