Skip to content
Last updated: 2026-04-06
Reference

API Performance Optimization

Optimize your Dxtra API integration for production performance and scalability.

Response Time Guidelines

Typical response times for well-optimized queries:

Operation Target Notes
GraphQL queries < 200ms Simple queries with limited fields
Mutations < 500ms Single-record operations
Batch operations < 2s Up to 100 records

Performance Variability

Actual response times depend on query complexity, data volume, and network conditions. Complex nested queries or large result sets may take longer.

Query Optimization

Request Only Needed Fields

GraphQL
# Avoid: Overfetching data
query GetDataSubjects {
  dataSubjects {
    id
    did
    createdAt
    updatedAt
    dataProcessingActivities {
      id
      typeId
      triggeredAt
      fieldIds
      preferenceIds
    }
  }
}

# Better: Request only needed fields with limits
query GetDataSubjectsOptimal {
  dataSubjects {
    id
    did
    dataProcessingActivities(limit: 1, order_by: {triggeredAt: desc}) {
      typeId
      triggeredAt
    }
  }
}

Caching Strategy

Implement caching for frequently accessed reference data:

JavaScript
const cache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes

const getCachedDataControllers = async () => {
  const cacheKey = 'dataControllers';
  const cached = cache.get(cacheKey);

  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.data;
  }

  const fresh = await client.request(GET_DATA_CONTROLLERS);
  cache.set(cacheKey, {
    data: fresh,
    timestamp: Date.now()
  });

  return fresh;
};

Batch Processing

JavaScript
// Avoid: Sequential API calls
const processSubjects = async (subjects) => {
  const results = [];
  for (const subject of subjects) {
    const result = await processDataSubject(subject);
    results.push(result);
  }
  return results;
};

// Better: Use batch mutations
const processBatchSubjects = async (subjects) => {
  const mutation = `
    mutation ProcessBatch($objects: [dataSubjects_insert_input!]!) {
      insert_dataSubjects(objects: $objects) {
        returning {
          id
          did
        }
      }
    }
  `;

  return client.request(mutation, { objects: subjects });
};

Connection Management

Reuse Client Instances

JavaScript
class DXTRAClient {
  constructor(jwt) {
    this.client = new GraphQLClient('https://api.dxtra.ai/v1/graphql', {
      headers: {
        'Authorization': `Bearer ${jwt}`,
        'X-Hasura-Role': 'user'
      },
      keepAlive: true,
      timeout: 30000
    });
  }

  async healthCheck() {
    return this.client.request('{ __typename }');
  }
}

Pagination

Use offset-based pagination for large datasets:

GraphQL
query GetDataSubjectsPaginated($offset: Int = 0, $limit: Int = 50) {
  dataSubjects(
    offset: $offset
    limit: $limit
    order_by: { createdAt: asc }
  ) {
    id
    did
    createdAt
  }
  dataSubjectsAggregate {
    aggregate {
      count
    }
  }
}

Performance Monitoring

Request Timing

JavaScript
const performanceWrapper = async (operation, query, variables) => {
  const start = Date.now();

  try {
    const result = await client.request(query, variables);
    const duration = Date.now() - start;

    console.log(`${operation} completed in ${duration}ms`);

    if (duration > 1000) {
      console.warn(`Slow query detected: ${operation} (${duration}ms)`);
    }

    return result;
  } catch (error) {
    const duration = Date.now() - start;
    console.error(`${operation} failed after ${duration}ms:`, error);
    throw error;
  }
};

Performance Anti-Patterns

N+1 Query Problem

GraphQL
# Avoid: Separate queries per subject
query GetSubjects {
  dataSubjects {
    id
    did
  }
}
# Then separately query activities for each subject

# Better: Single query with relationships
query GetSubjectsWithActivities {
  dataSubjects {
    id
    did
    dataProcessingActivities(limit: 1, order_by: {triggeredAt: desc}) {
      typeId
      triggeredAt
    }
  }
}

Excessive Polling

JavaScript
// Avoid: Constant polling
setInterval(() => {
  checkStatus();
}, 1000); // Every second

// Better: Use GraphQL subscriptions for real-time updates,
// or poll at reasonable intervals (30+ seconds)

Unbounded Result Sets

JavaScript
// Avoid: Fetching all records at once
const processAllSubjects = async () => {
  const allSubjects = await getAllDataSubjects(); // Could be thousands
  return processInMemory(allSubjects);
};

// Better: Process in batches with pagination
const processSubjectsInBatches = async () => {
  let offset = 0;
  const batchSize = 100;
  let hasMore = true;

  while (hasMore) {
    const batch = await getDataSubjectsBatch(offset, batchSize);
    await processBatch(batch.dataSubjects);
    offset += batchSize;
    hasMore = batch.dataSubjects.length === batchSize;
  }
};

Production Configuration

JavaScript
const productionClient = new GraphQLClient('https://api.dxtra.ai/v1/graphql', {
  timeout: 30000,
  retries: 3,
  retryDelay: (attempt) => Math.pow(2, attempt) * 1000,
  credentials: 'omit',
  mode: 'cors'
});

Next Steps