Explore the directory
Skip to article
Choosing an SDK

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 forQuestions to answer
ProvenanceIs it maintained by the provider or the community? Is the repository linked from official docs?
Runtime fitDoes the documented runtime match your deployment? Are native modules or Node APIs required?
API coverageDoes it support your exact operation, including the options you cannot give up?
MaintenanceAre releases, migration notes, and issue responses consistent with your needs?
Failure modelHow are HTTP errors, transport failures, timeouts, and partial results represented?
Operational fitCan you set deadlines, inspect request IDs, and understand retry behavior?

Run a small integration spike

  1. Install the official package in a throwaway branch or isolated example.
  2. Make one happy-path call with realistic input.
  3. Trigger one validation error and one controlled timeout.
  4. Record the useful result, native error details, and any missing capabilities.
  5. 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.

App-owned boundary · illustrative
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.