Speakeasy Logo
Skip to Content

In depth: Speakeasy vs Fern

Nolan Sullivan

Nolan Sullivan

February 1, 2025 - 14 min read


Speakeasy  and Fern  both offer free and paid services that API developers use to create SDKs (client libraries) and automate SDKs’ publication to package managers, but how do they differ? Here’s the short answer:

  1. Fern is an SDK generation tool designed for the Fern domain-specific language (DSL). It creates SDKs in seven languages and API reference documentation.
  2. Speakeasy is a complete platform for building and exposing enterprise APIs. It is OpenAPI-native and supports SDK generation in ten languages, as well as Terraform providers and documentation.

How is Speakeasy different?

Speakeasy is everything you need in one

We’ve built a platform that does more than merely generate SDKs. You could use Fern for SDKs, Stoplight for documentation, Spectral for linting, and handroll your Terraform provider, or you could use Speakeasy to do it all. One platform, one team, all your API needs handled.

OpenAPI-native vs OpenAPI-compatible

Speakeasy is designed to be OpenAPI-native. We don’t believe the world needs another standard for describing APIs. OpenAPI has its flaws, but it’s the established standard, and we’re committed to making it better. That means that Speakeasy is interoperable with the rest of the API tooling ecosystem. Mix and match us with your other favorite tools, and we’ll play nice.

Fern is built on top of a DSL (domain-specific language) , with optional support for OpenAPI. This makes Fern OpenAPI-compatible, meaning your OpenAPI document is no longer the single source of truth for your API.

Engineering velocity and maturity

Fern’s initial GitHub commit was in April 2022 , and the tool has expanded its language support to seven languages since then. By comparison, Speakeasy’s first commit was in September 2022 , and the platform has released support for ten languages in a shorter period.

The Speakeasy platform is also broader, with support for additional generation features not supported by Fern, like React Hooks and Terraform providers.

Speakeasy SDKs work where you need them

Speakeasy SDKs are designed to work in any environment. Speakeasy supports the latest versions of the languages it targets, and we’re committed to staying up to date with new releases. Our TypeScript SDKs can be bundled for the browser and many other JavaScript environments, while Fern’s are Node.js-only.

Speakeasy gets high-quality products in the hands of our users fast.

Comparing Speakeasy and Fern

SDK generation

Everyone has that one odd language that is critically important to their business and seemingly to nobody else’s. That’s why we’re committed to supporting the long tail. We’ve made a dent, but we’ve got further to go. Is there a language you need that we don’t support? Join our Slack community  to let us know.

SDK Generation Support

Language
Go
Speakeasy
Fern
Python
Speakeasy
Fern
TypeScript
Speakeasy
Fern
Java
Speakeasy
Fern
C#
Speakeasy
Fern
PHP
Speakeasy
Fern
Ruby
Speakeasy
Fern
Terraform
Speakeasy
Fern
Swift
Speakeasy
Fern
Unity
Speakeasy
Fern

SDK features

Fern and Speakeasy SDKs differ in two key areas of feature support:

  1. Fern lacks native support for some of the more advanced enterprise features supported by Speakeasy. Features like pagination and OAuth are left up to the customer to implement with custom code.
  2. Fern offers customizations to the names used in the SDK but not to the fundamental structure of the SDK. In addition to names, Speakeasy allows you to customize details like the directory structure and how parameters are passed into functions.

SDK Features

Feature
Union types
Speakeasy
Fern
Server-side events
Speakeasy
Fern
Retries
Speakeasy
Fern
Webhooks
Speakeasy
Fern
Async support
Speakeasy
Fern
Custom SDK naming
Speakeasy
Fern
Pagination
Speakeasy
Fern
API documentation
Speakeasy
Fern
Streaming uploads
Speakeasy
Fern
OAuth 2.0
Speakeasy
Fern
React Hooks support
Speakeasy
Fern
Caching and state management
Speakeasy
Fern
Customized SDK structure
Speakeasy
Fern

Platform features

The primary differences between the platforms are:

  1. Fern is solely focused on the generation of artifacts. Speakeasy has a deeper platform that supports the management of API creation through CLI validation.
  2. Speakeasy offers a web interface for managing and monitoring the creation of your SDKs.

Platform Features

Feature
GitHub CI/CD
Speakeasy
Fern
⚠️
CLI
Speakeasy
Fern
Web interface
Speakeasy
Fern
Package publishing
Speakeasy
Fern
Product documentation
Speakeasy
Fern
Server stubs
Speakeasy
Fern
OpenAPI validation
Speakeasy
Fern
OpenAPI Overlays
Speakeasy
Fern
AI-powered spec edits
Speakeasy
Fern

⚠️ Fern claims CI/CD support for SDKs on its paid plan, but this feature is not mentioned in the documentation.

Dependencies and SBOM (Software Bill of Materials)

From day one, Speakeasy has prioritized efficiency, and we’ve kept the dependency trees for our generated SDKs as lean as possible. For example, here’s the dependency graph for the Vercel SDK , an SDK generated by Speakeasy. It has zero direct dependencies, and one peer dependency (Zod).

Vercel dependency graph

By contrast, here’s the dependency graph for the ElevenLabs SDK , an SDK generated by Fern. It has many dependencies, which in turn have transitive dependencies, leading to a much more bloated SDK that is harder to maintain.

ElevenLabs dependency graph

Having more dependencies isn’t only bad in terms of efficiency. Many libraries might have only a single maintainer (the ElevenLabs SDK has 36 of these). This means any of these libraries could become unmaintained without warning. Similarly, many dependencies might have unaddressed critical vulnerabilities (CVs), leaving the upstream SDK vulnerable as well.

Enterprise support

Speakeasy sets up tracking on all customer repositories and will proactively triage any issues that arise.

Enterprise Support

Feature
Concierge onboarding
Speakeasy
Fern
Private Slack channel
Speakeasy
Fern
Enterprise SLAs
Speakeasy
Fern
User-issues triage
Speakeasy
Fern

Pricing

The biggest difference between the two pricing models is the starter plan. Speakeasy offers one free SDK with unlimited endpoints, while Fern’s starter plan is paid.

Pricing

Plan
Free
Speakeasy
1 free published SDK
Fern
Scale-Up
Speakeasy
$250/mo/SDK; max 50 endpoints
Fern
$250/mo/SDK; max 50 endpoints
Business
Speakeasy
$600/mo/SDK; max 200 endpoints
Fern
$600/mo/SDK; max 150 endpoints
Enterprise
Speakeasy
Custom
Fern
Custom

Fern and Speakeasy walkthrough

Let’s walk through generating an SDK with both Fern and Speakeasy. This is well explained in the documentation, so we’ll keep it brief.

Both services support Linux, macOS, and Windows, and run in Docker.

Some of the examples below are from the Speakeasy Bar Starter SDK .

Creating SDKs

Fern quickstart

Follow the Fern quickstart .

In the folder containing the openapi.yaml file, open a terminal and use Node.js with npm:

  • init creates a fern folder containing a copy of the OpenAPI document and some configuration files.
  • generate creates SDKs in the folder ../generated. You can change the output folder by editing generators.yaml. We used the following file to create all four languages:

Fern can also generate documentation:

  • init --docs creates a docs.yml configuration file.
  • generate --docs; creates documentation at the URL specified in the configuration file.

Speakeasy quickstart

Follow the Speakeasy quickstart .

The Speakeasy CLI is a single executable file built with Go .

  • Speakeasy handles authentication with a secret key in an environment variable. You can get the secret key on the Speakeasy website.
  • Running the Speakeasy quickstart launches an interactive mode that will guide you through generating an SDK.

Comparing TypeScript SDK generation with Fern and Speakeasy

Comparing the output of Fern and Speakeasy for all four SDK languages Fern supports would be too long for this article. We’ll focus on TypeScript (JavaScript).

SDK structure

Below is the Fern folder structure.

Below is the Speakeasy folder structure.

Speakeasy includes a documentation folder next to the SDK folder.

Speakeasy creates a complete npm package, with a package.json file, that is ready to be published to the npm registry. With Fern, you have to do extra work to prepare for publishing.

The structure of the SDK also has some bearing on the DevEx. To call order functions in the SDKs, you would use api/resources/orders/Client.js in Fern and src/sdk/orders.ts in Speakeasy.

Example SDK method

Let’s take a look at the code for a single call, createOrder, in Fern and Speakeasy.

Type safety

Both Fern and Speakeasy ensure that, if the input is incorrect, the SDK will throw an error instead of silently giving you incorrect data.

Fern uses a custom data serialization validator to validate every object received by your SDK from the server. See an example of this in api/resources/pet/client/Client.ts, where the line return await serializers.Pet.parseOrThrow(_response.body, { calls into the core/schemas/builders code.

Speakeasy uses Zod , an open-source validator, eliminating the need for custom serialization code.

File streaming

Streaming file transmission allows servers and clients to do gradual processing, which is useful for playing videos or transforming long text files.

Fern supports file streaming  but with the use of a proprietary endpoint extension, x-fern-streaming: true.

Speakeasy supports the Streams API  web standard automatically. You can use code like the following to upload and download large files:

React Hooks

React Hooks simplify state and data management in React apps, enabling developers to consume APIs more efficiently.

Fern does not support React Hooks natively. Developers must manually integrate SDK methods into state management tools like React Context, Redux, or TanStack Query.

Speakeasy generates built-in React Hooks using TanStack Query . These hooks provide features like intelligent caching, type safety, pagination, and seamless integration with modern React patterns such as SSR and Suspense.

Here’s an example:

In this example, the useQuery hook fetches data from an API endpoint. The cache key ensures unique identification of the query. The status variable provides the current state of the query: loading, error, or success. Depending on the query status, the component renders loading, error, or the fetched data as a list.

Auto-pagination

Speakeasy’s React Hooks also enable auto-pagination, which automatically fetches more data when the user scrolls to the bottom of the page. This feature is useful for infinite scrolling in social media feeds or search results.

Fern also supports pagination, but only offset- and cursor-based pagination, and these require additional configuration.

For an in-depth look at how Speakeasy uses React Hooks, see our official release article .

Webhooks support

Webhooks enable users to receive real-time updates from your API through HTTP callbacks in your SDK. Both Speakeasy and Fern generate SDKs that support webhooks and provide built-in support for webhook validation, payload parsing, and delivery.

However, the way the platforms handle webhooks differs slightly. Speakeasy provides a higher-level abstraction that includes validation and event type inference, whereas Fern requires manual event handling after signature verification.

We’ll use an example bookstore API to demonstrate how both SDKs handle webhooks.

First we’ll look at the OpenAPI definition for the webhook:

Here’s how you would handle the webhook using the SDKs:

You can read more about how Speakeasy handles webhooks in our webhooks release post.

OAuth client credentials handling

Both Speakeasy and Fern generate SDKs that handle OAuth 2.0 with client credentials, offering similar functionality in managing the token lifecycle and authentication processes.

Our bookstore API requires an OAuth 2.0 token with client credentials to access the API. Let’s see how the SDKs handle this.

Consider the following OAuth 2.0 configuration from the OpenAPI document:

Let’s look at how you can use the SDKs to create a new book in the bookstore API and how to handle OAuth 2.0 authentication.

Both Speakeasy and Fern SDKs handle OAuth 2.0 automatically – you provide credentials when creating the client, and the SDK manages token lifecycle, refreshes, and errors for you without additional manual handling.

Fern-generated SDK case study: Cohere TypeScript

Let’s take a closer look at a real-world SDK generated by Fern for a more complete view of Fern’s SDK generation. We inspected the Cohere TypeScript SDK  and here’s what we found.

SDK structure

The Cohere SDK’s repository is deeply nested, reminiscent of older Java codebases. This may reflect the generator’s codebase, or it may be due to the generator’s templates being designed by developers who aren’t TypeScript specialists.

There is a separation between core SDK code and API-specific code such as models and request methods, but internal SDK tools that hide behind layers of abstraction are not marked clearly as internal. This can lead to breaking changes in users’ applications in the future.

Speakeasy addresses these problems by clearly separating core internal code into separate files, or marking individual code blocks as clearly as possible for internal use. Repository structure and comments follow the best practices for each SDK’s target platform, as designed by specialists in each platform.

Data validation libraries

Both Speakeasy and Fern generate SDKs that feature runtime data validation. We’ve observed that Speakeasy uses Zod, a popular and thoroughly tested data validation and schema declaration library.

The Cohere TypeScript SDK, on the other hand, uses a custom Zod-like type-checking library, which ships as part of the SDK. Using a hand-rolled type library is a questionable practice for various reasons.

Firstly, it ships type inference code as part of the SDK, which adds significant complexity.

Here’s an example of date type inference  using complex regular expression copied from Stack Overflow.

While Zod uses a similar regex-based approach to dates under the hood, we know that Zod’s types and methods are widely used, tested by thousands of brilliant teams each day, and are supported by stellar documentation .

Furthermore, using Zod in SDKs created by Speakeasy allows users to include Zod as an external library when bundling their applications. This is what Speakeasy encourages, by including Zod as a peer dependency to the SDK.

A hand-rolled type library will almost certainly lead to safety issues that are challenging to debug and impossible to find answers for from other developers, as there is no community support.

Documentation

Apart from a short README, the Cohere TypeScript SDK does not include any documentation. This is in stark contrast to SDKs created by Speakeasy, which contain copy-paste usage examples for all methods and documentation for each model. Speakeasy SDKs are also supported by Zod’s detailed and clear documentation regarding types and validation.

Readability

SDK method bodies in the Cohere SDK are extremely long, unclear, and contain repeated verbose response-matching code. As a result, methods are difficult to read and understand at a glance.

Response matching in SDK methods involves long switch statements that are repeated in each method. The snippet below from the Cohere SDK is repeated multiple times.

By contrast, Speakeasy creates SDKs with improved readability by breaking SDK functionality into smaller, more focused methods, without hiding important steps behind multiple layers of abstraction.

Open enums

Both Speakeasy and Fern generate SDKs that allow users to pass unknown values in fields that are defined as enums if the SDK is configured to do so. This is useful to keep legacy SDKs working when an API changes.

However, where Speakeasy SDKs clearly mark unknown enum values by wrapping them in an Unrecognized type, SDKs generated by Fern use a type assertion. By not marking unrecognized enum values as such, Fern undermines the type safety TypeScript users rely on.

Consider the following OpenAPI component:

Based on this definition, Speakeasy will allow users to set the value of the BackgroundColor string to yellow, but will mark it as unrecognized. Here’s an example of what this looks like in TypeScript:

In the Cohere SDK generated by Fern, we found this enum:

When we looked at the definition of core.serialization.enum_, we found that any string value can be passed as a status, and would be represented as type Status.

SDK and bundle size

Both Speakeasy and Fern SDKs include runtime data validation, which can increase the bundle size. However, Speakeasy SDKs are designed to be tree-shakable, so you can remove any unused code from the SDK before bundling it.

Speakeasy also exposes a standalone function for each API call, which allows you to import only the functions you need, further reducing the bundle size.

Creating bundles

Let’s compare the bundle sizes of the SDKs generated by Speakeasy and Fern.

Start by adding a speakeasy.ts file that imports the Speakeasy SDK:

Next, add a fern.ts file that imports the Fern SDK:

We’ll use esbuild to bundle the SDKs. First, install esbuild:

Next, add a build.js script that uses esbuild to bundle the SDKs:

Run the build.js script:

This generates two bundles, dist/speakeasy.js and dist/fern.js, along with their respective metafiles.

Bundle size comparison

Now that we have two bundles, let’s compare their sizes.

First, let’s look at the size of the dist/speakeasy.js bundle:

Next, let’s look at the size of the dist/fern.js bundle:

The SDK generated by Fern is significantly larger than that built with the SDK generated by Speakeasy.

We can use the metafiles generated by esbuild to analyze the bundle sizes in more detail.

Analyzing bundle sizes

The metafiles generated by esbuild contain detailed information about which source files contribute to each bundle’s size, presented as a tree structure.

We used esbuild’s online bundle visualizer  to analyze the bundle sizes.

Here’s a summary of the bundle sizes:

The dist/speakeasy.js bundle’s largest contributor, at 72.3%, is the Zod library used for runtime data validation. The Zod library’s tree-shaking capabilities are a work in progress, and future versions of SDKs are expected to have smaller bundle sizes.

Speakeasy bundle size

The dist/fern.js bundle includes bundled versions of node-fetch, polyfills, and other dependencies, which contribute to the larger bundle size. Fern’s SDKs also include custom serialization code and a validation library, which can increase the bundle size.

Fern bundle size

Bundling for the browser

Speakeasy SDKs are designed to work in a range of environments, including the browser. To bundle an SDK for the browser, you can use a tool like esbuild or webpack.

Here’s an example of how to bundle the Speakeasy SDK for the browser using esbuild:

Doing the same for the Fern SDK generates an error, as the SDK is not designed to work in the browser out of the box.

Summary

Speakeasy’s additional language support and SDK documentation make it a better choice than Fern for most users.

If you are interested in seeing how Speakeasy stacks up against other SDK generation tools, check out our post .

Last updated on

Organize your
dev universe,

faster and easier.

Try Speakeasy Now