Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
{% extends "default.html" %}
{% set svgicons={
twitter: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -4 24 24" width="24" height="24" preserveAspectRatio="xMinYMin" class="icon__icon twitter"><path fill="currentColor" d="M20 1.907a8.292 8.292 0 0 1-2.356.637A4.07 4.07 0 0 0 19.448.31a8.349 8.349 0 0 1-2.607.98A4.12 4.12 0 0 0 13.846.015c-2.266 0-4.103 1.81-4.103 4.04 0 .316.036.625.106.92A11.708 11.708 0 0 1 1.393.754a3.964 3.964 0 0 0-.554 2.03c0 1.403.724 2.64 1.824 3.363A4.151 4.151 0 0 1 .805 5.64v.05c0 1.958 1.415 3.591 3.29 3.963a4.216 4.216 0 0 1-1.08.141c-.265 0-.522-.025-.773-.075a4.098 4.098 0 0 0 3.832 2.807 8.312 8.312 0 0 1-5.095 1.727c-.332 0-.658-.02-.979-.056a11.727 11.727 0 0 0 6.289 1.818c7.547 0 11.673-6.157 11.673-11.496l-.014-.523A8.126 8.126 0 0 0 20 1.907z"></path></svg>',
npm: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" preserveAspectRatio="xMinYMin" class="icon__icon npm"><path fill="currentColor" d="m11.993645 4.3033562h-7.7839999v15.7031878h7.7831879v-11.7431878h3.96v11.7431878h3.96v-15.7031878zm-9.9319999-2.148h19.9999999v19.9999998h-19.9999999z"></path></svg>',
github: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="-2 -2 24 24" width="24" height="24" preserveAspectRatio="xMinYMin" class="icon__icon github"><path fill="currentColor" d="M18.88 1.099C18.147.366 17.265 0 16.233 0H3.746C2.714 0 1.832.366 1.099 1.099.366 1.832 0 2.714 0 3.746v12.487c0 1.032.366 1.914 1.099 2.647.733.733 1.615 1.099 2.647 1.099H6.66c.19 0 .333-.007.429-.02a.504.504 0 0 0 .286-.169c.095-.1.143-.245.143-.435l-.007-.885c-.004-.564-.006-1.01-.006-1.34l-.3.052c-.19.035-.43.05-.721.046a5.555 5.555 0 0 1-.904-.091 2.026 2.026 0 0 1-.872-.39 1.651 1.651 0 0 1-.572-.8l-.13-.3a3.25 3.25 0 0 0-.41-.663c-.186-.243-.375-.407-.566-.494l-.09-.065a.956.956 0 0 1-.17-.156.723.723 0 0 1-.117-.182c-.026-.061-.004-.111.065-.15.07-.04.195-.059.378-.059l.26.04c.173.034.388.138.643.311a2.1 2.1 0 0 1 .631.677c.2.355.44.626.722.813.282.186.566.28.852.28.286 0 .533-.022.742-.065a2.59 2.59 0 0 0 .585-.196c.078-.58.29-1.028.637-1.34a8.907 8.907 0 0 1-1.333-.234 5.314 5.314 0 0 1-1.223-.507 3.5 3.5 0 0 1-1.047-.872c-.277-.347-.505-.802-.683-1.365-.177-.564-.266-1.215-.266-1.952 0-1.049.342-1.942 1.027-2.68-.32-.788-.29-1.673.091-2.652.252-.079.625-.02 1.119.175.494.195.856.362 1.086.5.23.14.414.257.553.352a9.233 9.233 0 0 1 2.497-.338c.859 0 1.691.113 2.498.338l.494-.312a6.997 6.997 0 0 1 1.197-.572c.46-.174.81-.221 1.054-.143.39.98.424 1.864.103 2.653.685.737 1.028 1.63 1.028 2.68 0 .737-.089 1.39-.267 1.957-.177.568-.407 1.023-.689 1.366-.282.343-.633.63-1.053.865-.42.234-.828.403-1.223.507a8.9 8.9 0 0 1-1.333.235c.45.39.676 1.005.676 1.846v3.11c0 .147.021.266.065.357a.36.36 0 0 0 .208.189c.096.034.18.056.254.064.074.01.18.013.318.013h2.914c1.032 0 1.914-.366 2.647-1.099.732-.732 1.099-1.615 1.099-2.647V3.746c0-1.032-.367-1.914-1.1-2.647z"></path></svg>'
} %}
{% block content %}
<div class="hero" style="background-image: url(/{{ hashes['images/bg-pattern-dark.png'] }})">
<div class="hero-body">
<div class="container">
<h1 class="title"><img class="logo" src="/{{ hashes['images/fastify-logo-inverted.png'] }}" alt="Fastify" decoding="async" /></h1>
<h2 class="subtitle">Fast and low overhead web framework, for Node.js</h2>
<div class="github-buttons">
<a class="github-button" href="https://github.com/fastify/fastify" data-icon="octicon-star" data-size="large" data-show-count="true" aria-label="Star fastify/fastify on GitHub">Star</a>
<a class="github-button" href="https://github.com/fastify/fastify/fork" data-icon="octicon-repo-forked" data-size="large" aria-label="Fork fastify/fastify on GitHub">Fork</a>
<script async defer src="https://buttons.github.io/buttons.js"></script>
</div>
</div>
</div>
</div>
<section class="section">
<div class="container content">
<div class="columns is-centered">
<div class="column is-12">
<h1 class="title">Why</h1>
<p>
An efficient server implies a lower cost of the infrastructure, a better responsiveness under load and happy users.
How can you efficiently handle the resources of your server, knowing that you are serving the highest number of requests possible, without sacrificing security validations and handy development?
</p>
<p>
Enter Fastify. Fastify is a web framework highly focused on providing the best developer experience with the least overhead and a powerful plugin architecture, inspired by Hapi and Express. As far as we know, it is one of the fastest web frameworks in town.
</p>
</div>
</div>
</div>
</section>
<section class="section">
<div class="container content">
<div class="columns is-centered">
<div class="column is-12">
<h1 class="title">Who is using Fastify?</h1>
<p>Fastify is proudly powering a large ecosystem of organisations and products out there.</p>
<p>Discover <a href="/organisations">more organisations using Fastify</a>. Do you want your organisation to <a href="/organisations#how-to-be-featured">be featured here</a>?</p>
</div>
</div>
<div class="columns is-centered">
<div class="column is-12">
<ul class="organisations-list">
{% set shuffledOrganisations = data.organisations | shuffle %}
{% for organizationIndex in range(0, 12) %}
{% set organization = shuffledOrganisations[organizationIndex] %}
{% if organization %}
<li>
<a href="{{ organization.link }}" target="_blank" rel="noopener" rel="nofollow">
<img src="/{{ hashes['images/organisations/' + organization.image] }}" alt="{{ organization.name }} is using Fastify" loading="lazy" decoding="async" />
</a>
</li>
{% endif %}
{% endfor %}
</ul>
</div>
</div>
</div>
</section>
<section class="section alternate">
<div class="container content">
<div class="columns is-centered">
<div class="column is-12">
<h1 class="title">Core features</h1>
<p>These are the main features and principles on which fastify has been built:</p>
<ul>
<li><strong>Highly performant:</strong> as far as we know, Fastify is one of the fastest web frameworks in town, depending on the code complexity we can serve up to 30 thousand requests per second.</li>
<li><strong>Extensible:</strong> Fastify is fully extensible via its hooks, plugins and decorators.</li>
<li><strong>Schema based:</strong> even if it is not mandatory we recommend to use <a href="http://json-schema.org/" target="_blank" rel="noopener">JSON Schema</a> to validate your routes and serialize your outputs, internally Fastify compiles the schema in a highly performant function.</li>
<li><strong>Logging:</strong> logs are extremely important but are costly; we chose the best logger to almost remove this cost, <a href="https://github.com/pinojs/pino" target="_blank" rel="noopener">Pino</a>!</li>
<li><strong>Developer friendly:</strong> the framework is built to be very expressive and to help developers in their daily use, without sacrificing performance and security.</li>
<li><strong>TypeScript ready:</strong> we work hard to maintain a <a href="https://www.typescriptlang.org/" aria-label="Link to TypeScript website">TypeScript</a> type declaration file so we can support the growing TypeScript community.</li>
</ul>
</div>
</div>
</div>
</section>
<section class="section">
<div class="container content">
<div class="columns is-centered">
<div class="column is-12">
<h1 class="title">Quick start</h1>
<p>Get fastify with NPM:</p>
<pre><code class="shell">npm install fastify</code></pre>
<p>Then create <code>server.js</code> and add the following content:</p>
<div class="swappable-async-await">
<div class="swap-button-box">
<label for="async-await-swap-1">async/await</label>
<div class="toggle-checkbox">
<input type="checkbox" class="swappable-async-await-checkbox" id="async-await-swap-1" value="0" checked="" name="async-await-swap-1">
<label for="async-await-swap-1"></label>
</div>
</div>
<pre class="no-async swappable-async-await-code"><code class="javascript">// Require the framework and instantiate it
const fastify = require('fastify')({ logger: true })
// Declare a route
fastify.get('/', (request, reply) => {
reply.send({ hello: 'world' })
})
// Run the server!
fastify.listen({ port: 3000 }, (err) => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})</code></pre>
<pre class="async swappable-async-await-code"><code class="javascript">// Require the framework and instantiate it
const fastify = require('fastify')({ logger: true })
// Declare a route
fastify.get('/', async (request, reply) => {
return { hello: 'world' }
})
// Run the server!
const start = async () => {
try {
await fastify.listen({ port: 3000 })
} catch (err) {
fastify.log.error(err)
process.exit(1)
}
}
start()
</code></pre>
</div>
<p>Finally, launch the server with:</p>
<pre><code class="shell">node server</code></pre>
<p>and you can test it with:</p>
<pre><code class="shell">curl http://localhost:3000</code></pre>
<h2>Using CLI</h2>
<p>Get fastify-cli with NPM:</p>
<pre><code class="shell">npm install --global fastify-cli</code></pre>
<p>Then scaffold a new project with:</p>
<pre><code class="shell">fastify generate myproject</code></pre>
<h2>Request/Response validation and hooks</h2>
<p>Of course, Fastify can do much more than this.</p>
<p>For example, you can easily provide input and output validation using JSON Schema and perform specific operations before the handler is executed:</p>
<div class="swappable-async-await">
<div class="swap-button-box">
<label for="async-await-swap-2">async/await</label>
<div class="toggle-checkbox">
<input type="checkbox" class="swappable-async-await-checkbox" id="async-await-swap-2" value="0" checked="" name="async-await-swap-2">
<label for="async-await-swap-2"></label>
</div>
</div>
<pre class="no-async swappable-async-await-code"><code class="javascript">const fastify = require('fastify')({ logger: true })
fastify.route({
method: 'GET',
url: '/',
schema: {
// request needs to have a querystring with a `name` parameter
querystring: {
name: { type: 'string' }
},
// the response needs to be an object with an `hello` property of type 'string'
response: {
200: {
type: 'object',
properties: {
hello: { type: 'string' }
}
}
}
},
// this function is executed for every request before the handler is executed
preHandler: (request, reply, done) => {
// E.g. check authentication
done()
},
handler: (request, reply) => {
reply.send({ hello: 'world' })
}
})
fastify.listen({ port: 3000 }, (err) => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
})</code></pre>
<pre class="async swappable-async-await-code"><code class="javascript">const fastify = require('fastify')({ logger: true })
fastify.route({
method: 'GET',
url: '/',
schema: {
// request needs to have a querystring with a `name` parameter
querystring: {
name: { type: 'string' }
},
// the response needs to be an object with an `hello` property of type 'string'
response: {
200: {
type: 'object',
properties: {
hello: { type: 'string' }
}
}
}
},
// this function is executed for every request before the handler is executed
preHandler: async (request, reply) => {
// E.g. check authentication
},
handler: async (request, reply) => {
return { hello: 'world' }
}
})
const start = async () => {
try {
await fastify.listen({ port: 3000 })
} catch (err) {
fastify.log.error(err)
process.exit(1)
}
}
start()</code></pre>
</div>
<h2>TypeScript Support</h2>
<p>Fastify is shipped with a typings file, but you may need to install <code class="shell">@types/node</code>, depending on the Node.js version you are using.</p>
<p>The following example creates a http server.</p>
<p>We pass the relevant typings for our http version used.</p>
<p>By passing types we get correctly typed access to the underlying http objects in routes.</p>
<p>If using http2 we'd pass <code class="typescript">&#60;http2.Http2Server, http2.Http2ServerRequest, http2.Http2ServerResponse&#62;</code>.</p>
<p>For https pass <code class="typescript">http2.Http2SecureServer</code> or <code class="typescript">http.SecureServer</code> instead of Server.</p>
<p>This ensures within the server handler we also get <code class="typescript">http.ServerResponse</code> with correct typings on <code class="javascript">reply.res</code>.</p>
<div class="swappable-async-await">
<div class="swap-button-box">
<label for="async-await-swap-3">async/await</label>
<div class="toggle-checkbox">
<input type="checkbox" class="swappable-async-await-checkbox" id="async-await-swap-3" value="0" checked="" name="async-await-swap-3">
<label for="async-await-swap-3"></label>
</div>
</div>
<pre class="no-async swappable-async-await-code"><code class="javascript">import Fastify, { FastifyInstance, RouteShorthandOptions } from 'fastify'
import { Server, IncomingMessage, ServerResponse } from 'http'
const server: FastifyInstance<Server, IncomingMessage, ServerResponse> = Fastify({})
const opts: RouteShorthandOptions = {
schema: {
response: {
200: {
type: 'object',
properties: {
pong: {
type: 'string'
}
}
}
}
}
}
server.get('/ping', opts, (request, reply) => {
reply.send({ pong: 'it worked!' })
})
server.listen({ port: 3000 }, (err) => {
if (err) {
server.log.error(err)
process.exit(1)
}
const address = server.server.address()
const port = typeof address === 'string' ? address : address?.port
})</code></pre>
<pre class="async swappable-async-await-code"><code class="javascript">import Fastify, { FastifyInstance, RouteShorthandOptions } from 'fastify'
import { Server, IncomingMessage, ServerResponse } from 'http'
const server: FastifyInstance<Server, IncomingMessage, ServerResponse> = Fastify({})
const opts: RouteShorthandOptions = {
schema: {
response: {
200: {
type: 'object',
properties: {
pong: {
type: 'string'
}
}
}
}
}
}
server.get('/ping', opts, async (request, reply) => {
return { pong: 'it worked!' }
})
const start = async () => {
try {
await server.listen({ port: 3000 })
const address = server.server.address()
const port = typeof address === 'string' ? address : address?.port
} catch (err) {
server.log.error(err)
process.exit(1)
}
}
start()</code></pre>
</div>
<p>Visit the <a href="/docs/latest">Documentation</a> to learn more about all the features that Fastify has to offer.</p>
</div>
</div>
</div>
</section>
<section class="section alternate">
<div class="container content">
<div class="columns">
<div class="column is-6">
<h1 class="title">A fast web framework</h1>
<p>Leveraging our experience with Node.js performance, Fastify has been built from the ground up to be <strong>as fast as possible</strong>. Have a look at our <a href="/benchmarks">benchmarks section</a> to compare fastify performance to other common web frameworks.</p>
<div class="block">
<p><a class="button is-primary is-large is-flex-mobile" href="/benchmarks">Check out our benchmarks</a></p>
</div>
</div>
<div class="column is-6">
<h1 class="title">Ecosystem</h1>
<p>
Fastify has an ever-growing ecosystem of plugins. Probably there is already a plugin for your favourite database or template language.
Have a look at the <a href="/ecosystem">Ecosystem page</a> to navigate through the currently available plugins.
Can't you find the plugin you are looking for? No problem, <a href="/docs/master/Reference/Plugins">it's very easy to write one</a>!
</p>
<div class="block">
<!-- TAG: "Changed the statement to count plugins" -->
<a class="button is-primary is-large is-flex-mobile" href="/ecosystem">Explore {{ data.ecosystem.plugins.corePlugins | length + data.ecosystem.plugins.communityPlugins | length }} plugins</a>
</div>
</div>
</div>
</div>
</section>
<section class="section team">
<div class="container content">
<div class="columns is-centered">
<div class="column is-12">
<h1 class="title">The team</h1>
<p>In alphabetical order</p>
{% for section in data.team %}
<div class="content">
<h2>{{ section.name }}</h2>
</div>
<div class="columns is-multiline">
{% for member in section.people | sort(false, false, 'sortname') %}
<div class="column is-one-third">
<div class="media v-center">
<div class="media-left">
<figure class="image is-96x96 contributor-picture">
<img src="{{ member.picture }}" alt="{{ member.name }}'s profile picture" loading="lazy" decoding="async" >
</figure>
</div>
<div class="media-content">
<p class="title is-5">{{ member.name }}</p>
<p class="subtitle is-6 contributor-links">
{% for label, link in member.links %}
<a href="{{ link }}" target="_blank" rel="noopener" title="Check out {{member.name}}'s {{label}} profile">{{svgicons[label] | safe}}</a>
{% endfor %}
</p>
</div>
</div>
</div>
{% endfor %}
</div>
{% endfor %}
</div>
</div>
</div>
</section>
<section class="section alternate">
<div class="container content">
<div class="columns is-centered">
<div class="column is-6">
<h1 class="title">Acknowledgments</h1>
<p>This project is kindly <strong>sponsored by</strong>:</p>
<ul>
{% for link in data.acknowledgements.sponsors %}
<li>
<a href="{{ link.url }}" target="_blank" rel="noopener">{{ link.name }}</a>
</li>
{% endfor %}
</ul>
<p>Past Sponsors:</p>
<ul>
{% for link in data.acknowledgements.past_sponsors %}
<li>
<a href="{{ link.url }}" target="_blank" rel="noopener">{{ link.name }}</a>{% if link.reason %} ({{ link.reason }}){% endif %}
</li>
{% endfor %}
</ul>
<p>Also thanks to:</p>
<ul>
{% for link in data.acknowledgements.others %}
<li>
<a href="{{ link.url }}" target="_blank" rel="noopener">{{ link.name }}</a>{% if link.reason %} ({{ link.reason }}){% endif %}
</li>
{% endfor %}
</ul>
</div>
<div class="column is-6">
<h1 class="title">Hosted by</h1>
<p>We are an At Large project at the <a href="https://openjsf.org/" target="_blank" rel="noopener">OpenJS Foundation</a>.</p>
<p>
<a href="https://openjsf.org/" target="_blank" rel="noopener">
<img id="openjs-logo" src="/{{ hashes['images/openjsf-knockout.svg'] }}" alt="OpenJS Logo" loading="lazy" decoding="async" />
</a>
</p>
</div>
</div>
</div>
</section>
{% endblock %}
{% block extraScripts %}
<script type="text/javascript">
(function() {
var state = { preferAsync: true }
function getAsyncToggles() {
return document.getElementsByClassName('swappable-async-await-checkbox')
}
function getCodeBlocks() {
return document.getElementsByClassName('swappable-async-await-code')
}
function initAsyncToggle() {
var toggles = getAsyncToggles()
for (var i=0; i < toggles.length; i++) {
toggles.item(i).addEventListener('change', function (e) {
state.preferAsync = e.target.checked
updateView()
})
}
}
function updateView() {
var toggles = getAsyncToggles()
for (var i=0; i < toggles.length; i++) {
toggles.item(i).checked = state.preferAsync
}
var codeBlocks = getCodeBlocks()
for (var i=0; i < codeBlocks.length; i++) {
var block = codeBlocks.item(i)
var show = (block.className.indexOf('async') === 0 && state.preferAsync) ||
(block.className.indexOf('no-async') === 0 && !state.preferAsync)
block.style.display = show ? 'block' : 'none'
}
}
initAsyncToggle()
updateView()
})()
</script>
{% endblock %}