- Getting Started
- Available Scripts
- Services
- OpenAPI Documentation
- React App
- REPL
- Database
- Database Migrations
- Background Jobs
- Learn More
Clone the repos and run pnpm install
to install the dependencies.
# clone the repo into a new project and remove the git history
git clone https://github.com/Pushpress/fastify-app-template.git my-project
rm -rf .git
# use a tool like nvm to ensure you are using the correct node version
nvm use
# install dependencies
pnpm install
Use npm-check-updates to bring the dependencies up to date. If there are any breaking changes, please open a PR on the template repo!
npx npm-check-updates -i
Copy the .env.sample
file to .env
and update the values to match your environment.
# create the local development environment file
cp .env.sample .env
# create the test environment file
cp .env.sample .env.test
Install the latest pushpress SDK
pnpm i @pushpress/pushpress
Set up local development dependencies with docker compose
chmod +x init.sh
docker compose up -d
In the project directory, you can run:
To start the app in dev mode.
Open http://localhost:3000 to view it in the browser.
Configure the FASTIFY_PORT
environment variable to change the port.
Specify a SERVICE environment variable to configure which plugins execute.
Start the vite+react development server at the default port http://localhost:5173
For production mode
Run eslint
Run the test cases.
Note: make sure the runtime dependencies are up first - docker compose --env-file .env.test -f docker-compose.test.yml up -d
Start the server in a repl session. see REPL for more details.
The SERVICE
environment variable can be set to api
, worker
, or monolith
to run the app in a specific mode.
- The
/api
folder contains the api service, which should be primarily responsible for handling incoming requests and delegating to other services. - The
/worker
folder contains the worker service, which should be responsible for handling long running tasks. - The
/web
folder serves a vite react app at the root route as a static file. By default the web service also registers the API routes but it can be configured to only serve the app in the SPA folder. monolith
runs both the api and worker services in the same process, which is useful for simpler apps that dont need to scale workers or APIs indpendently
The fastify app template supports Web UIs from simple components to minimize initial complexity and maximize extensibility. Fastify efficiently serves static html through the @fastify/static
plugin. The template comes pre-built with a single page react app built with vite, but any html file will work.
A Swagger UI is generated automatically and is available at http://localhost:3000/docs
A read-eval-print-loop (REPL) is available for debugging and development. Repls are useful for easily testing functionality without having to write extra code.
The REPL exposes the server instance and all decorators on the server instance, which is different from the production environment, where plugins registered on the different services are encapsulated to maintain better isolation since they are deployed as separate processes.
Use the SERVICE environment variable to switch between the different services or use the --service
flag to start the repl with a specific service.
This template comes with a postres database and uses kysely for type safe database access. Kysely is a query builder rather than an ORM, so there is no magic happening under the hood. Its just SQL, but with high quality types.
Included are a few ecosystem tools to make working with a postgres database easier and safer, without reaching for an ORM.
kysely-codegen is used to generate typescript types from the database schema. kysely-ctl is used to manage database migrations.
PgAdmin is included in the local development docker compose file for local database administration at http://localhost:5050. Login with username admin@admin.com
and password admin
.
The fastify template depends on redis for caching and as the BullMQ back end. Redis is available in both local development and testing throught the included compose files. Redis Commander is also available in local development for improved inspection and debugging at http://localhost:8081
Kysely offers a type safe way to automate database migrations with kysely-ctl. Use the pnpm migrate <command>
to manage migrations, run pnpm migrate --help
for more information.
NOTE: This creates an "onReady" hook that will run the migrations when the server starts to automatically apply migrations. To disable this feature set MIGRATE_ON_START to false in the .env file
Background jobs are handled by bullmq and a lightweight wrapper called bullify, that provides a simpler way to build type safe queues, workers and the jobs they process.
Th BullMQ dashboard is available at http://localhost:3000/dashboard
Define a queue and its associated worker and job types in the queues
folder using the bullify
function. Then decorate the fastify instance with the queues and workers. When adding a job to a queue the job data and any result type will be type checked, all underlying bullmq APIS and options are exposed with sensible defaults applied.
Some Best Practices:
- Configure a jobId when adding a job to the queue so jobs can remain idempotent
- Be mindful of the retry and job retention strategies, a job needs to be retained long enough for it to be retried and long enough to prevent duplicate jobs from being processed
- Configure concurrency limits on workers, since each worker defaults to processing running 1 job at a time
- When updating any recurring job, ensure that you either update an existing job configuration or delete the previous configuration and create a new one. It's possible to mistakenly create a new recurring (cron) job without deleting the old one.
- When unsure about how changing some BullMQ configuration may change its behavior, use redis commander to inspect the BullMQ key path contents. inspect queue metadata etc.
Run workers in the worker
folder using the .run
method on the worker. This way workers can be conditionally registered when running in a worker service, or when running in a monolith service.
To learn Fastify, check out the Fastify documentation.