EngineeringCategory

Gasket v7: How GoDaddy’s Framework Maker Powers Hundreds of Apps and Services

17 min read
Kawika Bader

The hidden cost of "getting started"

Picture this: You're a developer at a large tech company. Your team needs to build a new app or service. You know exactly what it should do, but first, you need to set up authentication, logging, monitoring, testing frameworks, linting rules, and ensure it follows company standards.

Sound familiar?

By the time you write your first line of business logic, two weeks have passed. Your "simple" application now has dozens of configuration files, and you're not even sure if you've set everything up correctly. Worse yet, the team down the hall is going through the exact same painful process.

At GoDaddy, we faced this challenge across many apps and services. Every team was reinventing the wheel, spending weeks on boilerplate setup instead of delivering value to customers. We needed a solution that would let developers go from idea to production-ready in hours, not weeks.

This is the problem Gasket solves.

What is Gasket?

Gasket is what we call a "Framework Maker": not just another framework, but a system for composing frameworks tailored to your organization's needs. Think of it as a plugin-powered platform that brings together all the tools and standards your teams need, while staying flexible enough to handle diverse use cases.

Here's the key insight: most organizations don't need another opinionated framework. They need a way to encode their own opinions, standards, and best practices into a reusable system that evolves with their needs.

How GoDaddy uses Gasket at scale

To understand why we built Gasket, you need to understand the scale at which GoDaddy operates. We're not just the world's largest domain registrar, with over 84 million domains registered. We power millions of small businesses with everything from hosting and email to website builders and online stores.

This means hundreds of internal apps and services, each with its own requirements. Before Gasket, each team faced the same challenges. Setting up a new service meant configuring build tools, establishing logging patterns, implementing authentication, and ensuring compliance with company standards. Teams were duplicating effort across the organization, each solving the same problems in slightly different ways.

The impact of Gasket has been transformative:

  • Dramatically reduced service setup time
  • More consistent deployments through standardized application structure
  • Lighter applications with Gasket v7's removal of CLI dependencies
  • Measurable increases in team velocity and developer productivity

But the real magic isn't in the metrics; it's in what happens when developers stop fighting boilerplate and start solving business problems. New team members become productive faster, experienced developers spend more time on innovation, and the entire organization benefits from shared solutions.

From internal tool to open source powerhouse

Gasket didn't start as a grand vision. It began with a simple observation: every team at GoDaddy was solving the same problems in slightly different ways. We had dozens of "starter kits" and "boilerplate repositories" floating around, each encoding someone's idea of best practices.

The breakthrough came when we stopped trying to build the "perfect" framework and started building a framework for making frameworks. Instead of prescribing solutions, Gasket provides the infrastructure for sharing and composing them.

What started as an internal solution to help GoDaddy's development teams ended up powering apps and services across the company at significant scale. This success convinced us other organizations facing similar challenges could benefit from the same approach.

The plugin architecture that changed everything

At its core, Gasket is deceptively simple. It's a plugin system with lifecycles - specific points where plugins can hook in to change behavior. But this simplicity enables powerful composition.

The following code shows how a basic Gasket application combines different plugins to create a fully functional app:

// A basic Gasket app in v7
import { makeGasket } from '@gasket/core';
import pluginNextjs from '@gasket/plugin-nextjs';
import pluginLogger from '@gasket/plugin-logger';
import pluginAuth from '@your-company/gasket-plugin-auth';

export default makeGasket({
  plugins: [
    pluginNextjs,    // Adds Next.js support
    pluginLogger,    // Adds structured logging
    pluginAuth       // Your custom auth solution
  ]
});
Gasket architecture diagram
Gasket architecture diagram

The Gasket v7 architecture: Plugins integrate through a central registry, expose actions via GasketActions API, and coordinate through lifecycle hooks

What makes this powerful is that each plugin can:

  • Add dependencies to your project
  • Configure build tools
  • Set up middleware
  • Define new commands
  • Hook into other plugins' lifecycles

This means your custom authentication plugin can automatically configure itself to work with the logging plugin, which integrates with your monitoring plugin, and so on. It's composition all the way down.

Presets: frameworks within the framework

While plugins provide features, presets provide opinions. A preset is simply a collection of plugins pre-configured to work together.

The following example shows what's included in common Gasket presets:

// @gasket/preset-nextjs includes:
// - Next.js plugin
// - Webpack plugin
// - Intl plugin
// - Production-ready configurations

// @your-company/preset-api might include:
// - Express/Fastify plugin
// - Your auth plugin
// - Your monitoring standards
// - Your API conventions

This two-level architecture (plugins for capabilities, presets for opinions) lets organizations encode their standards without losing flexibility. Teams get started quickly with presets but can always add or customize plugins as needed.

What makes Gasket different?

In a world full of JavaScript frameworks, what makes Gasket special? It's not about competing with Express, Next.js, or Fastify; it's about making them work better together.

Traditional frameworks ask: "What's the best way to build apps?" Gasket asks: "What's the best way for YOUR team to build apps?"

Instead of prescribing patterns, Gasket provides the infrastructure to encode and share your patterns. This fundamental difference changes everything:

Traditional FrameworkGasket Approach
"Use our router""Choose Express, Fastify, or bring your own"
"Follow our file structure""Define your own conventions via plugins"
"Learn our testing approach""Use Jest, Mocha, Vitest (whatever fits)"
"Adopt our deployment model""Integrate with your existing pipelines"

Lifecycle-driven architecture

Gasket's lifecycle system is what makes plugin composition possible. Each lifecycle represents a specific moment in your app's journey: from build time to request handling.

The following code demonstrates how an authentication plugin can hook into different lifecycle events:

export default {
  name: 'my-security-plugin',
  hooks: {
    // Build-time: Add security headers to webpack
    webpackConfig(gasket, config) {
      return addSecurityHeaders(config);
    },

    // Start-time: Set up security middleware
     express(gasket, app) {
       app.use(securityMiddleware);
     },

     // Request-time: Validate permissions
     async middleware(gasket) {
       return async function validateMiddleware(req, res, next) {
         await validatePermissions(req);
         next();
       }
     }
  }
};

This isn't just about organizing code; it's about creating predictable integration points where plugins can cooperate without tight coupling.

Progressive disclosure of complexity

One of Gasket's core principles is meeting developers where they are. New developers can start with a simple command:

npx create-gasket-app my-app --presets @gasket/preset-nextjs

The interactive prompts guide them through the setup, making sensible defaults available while allowing customization where needed. Once created, starting the app is straightforward:

cd my-app
npm run local

They now have a working Next.js app with best practices baked in. But when they need to customize something, the full power is there:

  • Start with presets
  • Add individual plugins as needed
  • Create custom plugins for your needs
  • Share plugins across teams
  • Eventually create your own presets
Gasket v7 Development flow
Gasket v7 Development flow

The Gasket development journey: Start simple, add complexity only as needed, iterate without friction

This progression from consumer to contributor happens naturally as teams grow.

Gasket in action

Now that you understand Gasket's philosophy and approach, let's see how it translates into real code. We'll build two different solutions to showcase its flexibility and show how quickly you can go from zero to production-ready.

Building an API with @gasket/preset-api

Want to build a production-ready API? Here's how simple the process is:

# Create the app
npx create-gasket-app weather-api --presets @gasket/preset-api

The create command will walk you through a series of choices to tailor the app to your needs:

? What is your app description?
? Which packager would you like to use? (npm/yarn/pnpm)
? Do you want to use Vitest for unit testing?
? Do you want to use TypeScript?
? Do you want to use Swagger?
? Which server framework would you like to use? (Express/Fastify)
? Do you want to use generated documentation?
? Do you want a git repo to be initialized?
? Which code style do you want configured?

After answering these prompts, Gasket sets up your project with all your selections properly configured. In just a few minutes, you have a working API with:

  • Express or Fastify configured
  • Structured logging via Winston
  • Health checks and monitoring
  • Swagger documentation
  • Production-ready error handling
  • Environment configuration support

Let's add a simple endpoint:

// plugins/weather-api.js
export default {
  name: 'weather-api',
  hooks: {
    express(gasket, app) {
      app.get('/api/weather/:city', async (req, res) => {
        const { city } = req.params;
        const logger = gasket.actions.getLogger();

        logger.info('Weather request', { city });

        // Your weather logic here
        const weather = await getWeatherData(city);
        res.json(weather);
      });
    }
  }
};

// gasket.js
import { makeGasket } from '@gasket/core';
import weatherApi from './plugins/weather-api.js';

export default makeGasket({
  plugins: [
    // Other plugins...
    weatherApi
  ]
});

// server.js
import gasket from './gasket.js';

// Fire up the server (this spins up Express or Fastify for you)
gasket.actions.startServer();

That's it. You have logging, error handling, monitoring, and documentation, all from those few lines.

Building a Next.js app with @gasket/preset-nextjs

For full-stack applications, the Next.js preset provides a comprehensive setup:

npx create-gasket-app customer-portal --presets @gasket/preset-nextjs

Like the API preset, prompts guide you through configuration choices specific to Next.js applications, including testing frameworks, TypeScript preferences, and styling options. Once configured, you get:

  • Next.js with App or Page Router support (@gasket/plugin-nextjs)
  • Internationalization (i18n) ready (@gasket/plugin-intl)
  • Performance monitoring (@gasket/plugin-elastic-apm)
  • SEO optimizations (built into Next.js)
  • Progressive Web App capabilities (@gasket/plugin-manifest@gasket/plugin-service-worker@gasket/plugin-workbox)
  • TypeScript support (optional) (@gasket/plugin-typescript)

Here's how you'd add authentication using GasketActions:

// api/validate.js
import gasket from '../../../gasket';

export default async function GET(req, res) {  
  // Validate auth with a GasketAction  
  const authResults = gasket.actions.checkAuth(req);  
  res.json(authResults);  
}
// pages/secure-page.js
import React from 'react';
import gasket from '../gasket';

function SecurePage({ secretData }) {
  return (
    <div>  
      <h1>Secret Data</h1>  
      <pre>{JSON.stringify(secretData, null, 2)}</pre>  
    </div> 
  );
}

SecurePage.getInitialProps = async ({ req, res }) => {
  let authResults  
  if (req) {  
    // Validate auth on the server with the GasketAction  
    authResults = gasket.actions.checkAuth(req);  
    if (!authResults.valid) {  
      res.writeHead(302, {Location: '/login'});  
      res.end();  
      return {  
        secretData: null  
      }  
    }  
  } else {  
    // On the client, call our auth validation API route  
    authResults = await fetch('/api/validate').then(r => r.json());  
    if (!authResults.valid) {  
      window.location.href = '/login';  
      return {  
        secretData: null  
      }  
    }  
  }  

  // If authenticated, fetch some protected data  
  const secretData = await fetch('https://api.example.com/secret-data', {  
    headers: {  
      'Authorization': `Bearer ${authResults.token}`  
    }  
  }).then(r => r.json());  

  return {  
    secretData  
  }  
};  


export default SecurePage;

Notice how GasketActions provide a consistent interface for accessing functionality, whether you're in an API route or a React component. No more prop drilling or context wrapping; just call the action you need.

The plugin architecture: Building blocks of innovation

Think of Gasket plugins like LEGO blocks: each one does something specific, but they're designed to work together. The magic happens when you combine them.

Anatomy of a plugin

A Gasket plugin is just a JavaScript object with a specific shape:

export default {
  name: '@your-company/gasket-plugin-analytics',
  
  // Hook into Gasket lifecycles
  hooks: {
    // Add analytics script to the build
    webpackConfig(gasket, config) {
      config.plugins.push(new AnalyticsPlugin());
      return config;
    },
    
    // Track server startup (runs once after plugins are initialized)
    async init(gasket) {
      await gasket.actions.trackEvent('server_started', {
        environment: gasket.config.env
      });
    }
  },
  
  // Provide actions other code can use
  actions: {
    async trackEvent(gasket, eventName, data) {
      // Your analytics logic here
    }
  }
};

How plugins compose

The real power comes from how plugins work together. Let's say you have three plugins:

  • Authentication Plugin: Handles user authentication
  • Analytics Plugin: Tracks user behavior
  • Feature Flag Plugin: Controls feature access

They can seamlessly integrate:

// feature-flag-plugin.js
export default {
  name: 'feature-flag-plugin',
  actions: {
    /**
     * Check if the visitor has a particular feature.
     */
    async hasFeature(gasket, req, featureName) {
      const visitor = await gasket.actions.getVisitor(req); // From visitor plugin
      const features = await getFeatureFlags(visitor);

      await gasket.actions.trackEvent('feature_accessed', {
        visitorId: visitor.id,
        feature: featureName
      });

      return features.includes(featureName);
    }
  }
};

No explicit dependencies. No tight coupling. Just plugins using each other's actions and respecting lifecycle order.

Lifecycle timing is the secret sauce

What prevents chaos when many plugins hook the same lifecycle? Timing controls:

export default {
  name: 'my-plugin',
  hooks: {
    middleware: {
      timing: {
        after: ['@gasket/plugin-auth'],    // Run after auth
        before: ['@gasket/plugin-logger']  // But before logging
      },
      handler(gasket, app) {
        // Your middleware logic
      }
    }
  }
};

This declarative approach means:

  • Plugins don't need to know about each other's internals
  • Order of operations is explicit and debuggable
  • New plugins can insert themselves anywhere in the chain

Less magic, more transparency with Gasket v7

Version 7 represents our biggest philosophical shift yet. We asked ourselves: what if we removed every bit of "magic" that makes debugging harder or learning curves steeper?

The great CLI removal

The boldest change? We removed the Gasket CLI entirely. Here's why:

Before (v6):

gasket build   # What webpack config is it using?
gasket start   # How is the server configured?
gasket local   # What's different from start?

Every command was a black box. Debugging meant diving into Gasket's internals.

After (v7):

next build     # Using Next.js? Use Next.js commands
npm run build  # Custom build? See package.json
node server.js # Start server? Just run it

This transparency has transformed the developer experience. Engineers now understand exactly what's happening at every step. Debugging is straightforward because there's no abstraction layer hiding the real commands. New developers familiar with Next.js or Express can immediately understand and change Gasket applications without learning proprietary CLI commands.

The end of request decoration with GasketActions

Remember the bad old days of decorated request objects?

// The old way (v6)
app.use(async (req, res, next) => {
  req.user = await getUser(req);
  req.permissions = await getPermissions(req.user);
  req.features = await getFeatures(req.user);
  req.logger = getLogger(req);
  // Is req.user available in the next middleware? 🤷
  next();
});

Every middleware added mystery properties. TypeScript couldn't help. Debugging was complex.

With GasketActions in v7:

// The new way (v7)
app.get('/api/data', async (req, res) => {
  const user = await gasket.actions.getUser(req);
  const permissions = await gasket.actions.getPermissions(req);
  const features = await gasket.actions.getFeatures(req);
  const logger = gasket.actions.getLogger();
  
  // Explicit. Typed. Debuggable.
});

Performance improvements that matter

The "less magic" approach brought unexpected benefits:

  • Smaller application footprint: Removing the CLI and its dependencies reduces the package size
  • Faster startup times: Direct execution removes command parsing overhead
  • Better tree shaking: ESM-first design allows build tools to remove dead code more effectively
  • Improved debugging: Standard Node.js tools work without interference from abstraction layers

These improvements compound in production environments. Lighter applications mean less to download and install. Faster startup times improve scaling responsiveness. Better tree shaking reduces bandwidth usage and improves application performance.

Modern JavaScript, finally

Gasket v7 embraces modern standards:

// ESM modules by default
import { makeGasket } from '@gasket/core';
import pluginNext from '@gasket/plugin-nextjs';

// Top-level await
const gasket = makeGasket({ plugins: [pluginNext] });
await gasket.ready;

// Direct framework integration
export default await gasket.actions.getNextConfig();

No more CommonJS/ESM translation layers. No more build tool magic. Just modern JavaScript that runs everywhere.

How does Gasket compare?

Let's address the elephant in the room: how does Gasket stack up against other popular frameworks? The answer might surprise you: we're not competing with them. We're making them better.

The apples and oranges problem

Comparing Gasket to Express, Fastify, or NestJS is like comparing a toolkit to a hammer. They solve different problems:

FrameworkWhat It DoesBest For
ExpressMinimal web frameworkSimple APIs, most flexibility
FastifyHigh-performance web frameworkSpeed-critical services
NestJSEnterprise application frameworkLarge, structured applications
GasketFramework makerMaking any of the above work better for your org

Gasket doesn't replace these frameworks; it enhances them.

Build your own vs. Gasket

The actual alternative to Gasket isn't another framework; it's building your own platform from scratch. Here's what that looks like:

ChallengeDIY ApproachGasket Approach
Initial SetupWeeks of boilerplatenpx create-gasket-app
Sharing StandardsCopy-paste templatesPlugins and presets
UpdatesManually update each serviceUpdate plugin version
OnboardingLong documentationWorking app in minutes
FlexibilityRewrite for changesAdd/remove plugins

GoDaddy's Gasket success story

What started as an experiment to reduce boilerplate has become the foundation for our entire Node.js ecosystem.

The benefits of Gasket are evident across every dimension of our development process:

Development Velocity:

Engineers can now go from initial idea to production-ready code in a fraction of the time required before. This acceleration means teams spend their time solving business problems rather than wrestling with configuration and setup.

Team Productivity:

Engineers can now effectively maintain many services thanks to the consistency Gasket provides. The cognitive load of switching between projects has decreased dramatically because every Gasket application follows familiar patterns. This standardization has freed engineers to focus on features rather than infrastructure.

From internal tool to open source

Gasket's success at GoDaddy led to a natural question: could this help other organizations facing similar challenges?

We're excited to see how the open-source community will continue to embrace Gasket, with developers from diverse organizations making contributions. We envision an ecosystem that grows beyond our initial scope — with community-driven plugins for GraphQL, Vite, Svelte, and more. Through collaboration, Gasket can become more robust and versatile than we could have achieved alone.

The GitHub repository continues to grow, attracting developers who recognize the value of a framework-making approach. Our aim is for Gasket to help organizations of all sizes standardize their Node.js development — and to show that the challenges we faced at GoDaddy are ones many modern teams can relate to.

Get started with Gasket

The beauty of Gasket is that you don't need to transform your entire organization to see benefits. Start small, prove the value, and grow from there.

Start your journey

For Individual Developers:

  1. Build your next side project with Gasket
  2. Experience the productivity boost firsthand
  3. Share your experience with your team

For Teams:

  1. Start with one new app or service
  2. Create your first shared plugin
  3. Document your patterns
  4. Share across projects

For Organizations:

  1. Identify common patterns across teams
  2. Build organizational presets
  3. Establish your platform standards
  4. Enable teams to move faster

Join the community

Gasket is more than code: it's a community of developers solving similar problems:

The future is composable

At GoDaddy, Gasket has fundamentally changed how we think about building services. Instead of asking "how do we build this?", we ask "what plugins do we need?" Instead of reinventing wheels, we're composing solutions

Gasket v7's "less magic" philosophy makes it easier than ever to adopt. There's no mysterious CLI to learn, no hidden behaviors to debug. Just compose the plugins you need, and let your framework do what it does best.

Whether you're a solo developer tired of boilerplate, a team lead looking to standardize practices, or an architect designing for scale, Gasket provides the foundation for building better, faster, and more maintainable applications.

Ready to transform how your team builds applications? Start with Gasket today and join the growing community of developers who've discovered a better way to build.

npx create-gasket-app

Welcome to the future of framework making.