Comparison
How Caller compares to Axios, ky, ofetch, and native fetch. Understand the trade-offs and choose the right HTTP client for your project.
Overview
The JavaScript ecosystem has many excellent HTTP clients. This page provides an honest comparison between Caller and popular alternatives, helping you understand when Caller is the right choice and when you might prefer something else.
We believe in picking the right tool for the job. Caller excels at type-safe, schema-validated API consumption in TypeScript projects—but it's not always the best choice for every scenario.
Quick Comparison
| Feature | Caller | Axios | ky | ofetch | fetch |
|---|---|---|---|---|---|
| Type Safety | ✅ Full inference | ⚠️ Manual | ⚠️ Manual | ⚠️ Manual | ❌ None |
| Schema Validation | ✅ Built-in | ❌ | ❌ | ❌ | ❌ |
| Fluent API | ✅ | ❌ | ✅ | ⚠️ Partial | ❌ |
| Retries | ✅ Built-in | ❌ Plugin | ✅ Built-in | ✅ Built-in | ❌ |
| Caching | ✅ Built-in | ❌ | ❌ | ❌ | ❌ |
| React Hooks | ✅ Built-in | ❌ | ❌ | ❌ | ❌ |
| Interceptors | ✅ | ✅ | ✅ | ✅ | ❌ |
| Bundle Size | ~8kb | ~13kb | ~4kb | ~5kb | 0kb |
| Node.js Support | ✅ | ✅ | ✅ | ✅ | ✅ 18+ |
| Browser Support | Modern | All | Modern | Modern | Modern |
Detailed Comparisons
Feature Deep Dive
Type Safety
The biggest differentiator between Caller and alternatives is the type system. Most HTTP clients require you to manually define interfaces and hope they match your API:
// You define this manually
interface User {
id: string;
name: string;
email: string;
}
// API changes "email" to "emailAddress"
// TypeScript doesn't know - runtime error!
const user = await axios.get<User>('/users/123');
console.log(user.data.email); // undefined at runtimeWith Caller, your schema is the source of truth:
// Schema is the source of truth
const schemas = IgniterCallerSchema.create()
.path('/users/:id', (path) =>
path.get({
responses: {
200: z.object({
id: z.string(),
name: z.string(),
emailAddress: z.string(), // API changed this
}),
},
})
)
.build();
const { data } = await api.get('/users/:id').execute();
console.log(data.emailAddress); // TypeScript knows the correct fieldReact Integration
Caller provides first-class React hooks, while other libraries require external wrappers like TanStack Query:
import { useCaller } from '@igniter-js/caller/client';
function UserProfile({ id }: { id: string }) {
const api = useCaller('main');
const { data, isLoading } = api.get('/users/:id')
.params({ id })
.useQuery({ staleTime: 10_000 });
return <div>{data?.name}</div>;
}import { useQuery } from '@tanstack/react-query';
import axios from 'axios';
function UserProfile({ id }: { id: string }) {
const { data, isLoading } = useQuery({
queryKey: ['user', id],
queryFn: () => axios.get(`/users/${id}`).then(r => r.data),
});
return <div>{data?.name}</div>;
}Migration Guides
From Axios
Step-by-step guide to migrate from Axios to Caller
From fetch
How to upgrade from native fetch to Caller
Summary
| Scenario | Recommendation |
|---|---|
| New TypeScript project with APIs | Caller |
| Existing Axios codebase, no time to migrate | Axios |
| Ultra-minimal bundle, simple needs | ky or fetch |
| Nuxt.js application | ofetch |
| IE11 support required | Axios |
| Type-safe, validated API layer | Caller |
Choose Caller when type safety, developer experience, and production-readiness matter. Choose alternatives when simplicity or specific compatibility requirements take priority.
Next Steps
Installation
Complete guide to installing and configuring @igniter-js/caller. Covers all package managers, TypeScript setup, optional dependencies, and environment configuration.
Request Builder
Master the fluent API for building type-safe HTTP requests. Learn how to configure URLs, bodies, headers, timeouts, caching, retries, and more with chainable methods.