Choosing an SDK
Choose the smallest dependency that does the job well in your runtime. A popular package is a starting point for evaluation, not the conclusion.
On this page
Define the job first
Write down the operation your application needs and the constraints it must respect. “Search” is broad. “Find five recent source URLs with snippets from an approved set of domains” gives you something concrete to evaluate.
- Runtime: browser, Node.js server, edge runtime, mobile, or a background worker?
- Data: what will leave your system, and where may it be processed?
- Behavior: streaming, pagination, transactions, cancellation, or idempotency?
- Operations: expected volume, response deadline, budget, and failure tolerance?
Evaluate the library
| Look for | Questions to answer |
|---|---|
| Provenance | Is it maintained by the provider or the community? Is the repository linked from official docs? |
| Runtime fit | Does the documented runtime match your deployment? Are native modules or Node APIs required? |
| API coverage | Does it support your exact operation, including the options you cannot give up? |
| Maintenance | Are releases, migration notes, and issue responses consistent with your needs? |
| Failure model | How are HTTP errors, transport failures, timeouts, and partial results represented? |
| Operational fit | Can you set deadlines, inspect request IDs, and understand retry behavior? |
Run a small integration spike
- Install the official package in a throwaway branch or isolated example.
- Make one happy-path call with realistic input.
- Trigger one validation error and one controlled timeout.
- Record the useful result, native error details, and any missing capabilities.
- Run it in the actual target runtime before committing to the dependency.
For an email integration, the Resend official Node.js repository and sending reference are useful primary sources. Follow the same source trail for every provider you evaluate.
Decide what to wrap
Start with the native client. Extract a narrow application boundary when your product has a stable operation to name. Keep provider-specific options close to the integration, and avoid designing a universal interface before you have a second real use case.
type ReceiptEmail = {
orderId: string;
recipient: string;
};
// Your product operation, not a universal email API.
export interface ReceiptSender {
sendReceipt(input: ReceiptEmail): Promise<{
messageId: string;
provider: string;
}>;
}SDK SDK is an independent discovery hub. Provider examples link to official documentation. App-owned examples are illustrative patterns you can adapt.