The backend is the part of your product that users never see. It stores data, checks who is logged in, takes payments and talks to other services. As a Node.js development company, we build backends in TypeScript that are easy to read and test, and easy to watch once they are live.
This page is about backend development. For the screens your users see, see React development or Next.js development.
APIs and backends in TypeScript
An API is how your frontend, your mobile app or a partner’s system asks your backend for data. We write every API in TypeScript, and we keep it predictable.
- We use Fastify or Hono for most APIs. For large codebases with several developers, NestJS gives a stricter structure.
- Zod checks every request before the code acts on it. Bad input gets a clear error message and never reaches the database.
- The API docs are generated from the same Zod schemas, in OpenAPI format. The docs cannot drift away from the code.
- Changes that would break an existing app go into a new version of the endpoint, so older clients keep working.
If you need a Node.js or TypeScript developer for an existing product, we can also work in your codebase at $60 an hour. For APIs that other companies connect to, see API development.
Background jobs and queues
Some work should not happen while a user waits. Examples are sending emails, generating PDFs, resizing images, syncing with accounting software and calling an AI model. We move that work to a queue, and a separate worker process handles it.
- BullMQ with Redis suits apps with a lot of jobs or strict timing.
- pg-boss keeps the queue inside PostgreSQL, so there is one less service to run and pay for.
Every job can run twice without doing damage, because networks fail and jobs get retried. A job that keeps failing moves to a separate list and sends an alert, so nobody has to notice it by chance. Scheduled tasks such as a nightly report or a monthly invoice run the same way.
Webhooks
A webhook is a message another service sends to your backend when something happens. Stripe sends one when a payment succeeds, and Shopify sends one when an order comes in. Webhooks look simple, but they cause many quiet bugs. We follow the same rules for each one.
- Check the signature, so only the real sender is accepted.
- Reply within a few seconds and put the actual work on the queue.
- Store the ID of each event and skip any event already handled. Stripe’s documentation says it retries failed deliveries for up to three days, so duplicates are normal.
- Log every event, so you can see what happened when a customer asks.
Integrations with third-party services
Most products depend on other services. Common ones are Stripe for payments and subscriptions, QuickBooks Online or Xero for accounting, HubSpot or Salesforce for customer records, and Postmark or Resend for email. Each one has its own limits on how often you can call it, its own login tokens that expire and its own way of failing.
We put each integration in its own module with one clear set of functions. The rest of the code never talks to the provider directly. If you switch accounting software later, the change stays in one place. For models such as OpenAI or Claude, see AI integration.
Databases with PostgreSQL and Supabase
We use PostgreSQL for almost every project. It handles most workloads well, and many hosts support it.
- Changes to the database structure are written as migration files with Drizzle or Prisma. They are reviewed like any other code change.
- We add indexes for the queries your app actually runs, and check slow queries after launch.
- Backups include point-in-time recovery. We test a restore before launch, because an untested backup may not work.
- On Supabase, row level security rules in the database make sure each customer can only read their own rows.
Logins and security basics
Logins are a bad place to be creative. We use proven tools such as Supabase Auth, Auth.js or Better Auth for email and password, magic links, and Google or Microsoft sign-in. Business customers can get single sign-on through their own identity provider.
For the rest of the backend, we guard against the risks listed in the OWASP Top 10:
- Check permissions on the server for every request, even when the screen hides the button.
- Use parameterized queries, so user input cannot change a database query.
- Keep secrets such as API keys in environment variables or a secret manager, never in the code.
- Limit how often someone can try to log in or call a public endpoint.
- Keep dependencies up to date with automatic update pull requests.
Monitoring and logs
A backend needs someone to know when it breaks. We set up error tracking with Sentry, so a crash sends an alert with the exact line of code. Logs are structured, and each request gets an ID. That lets us follow one customer’s request through the API, the queue and the database. Uptime checks call a health endpoint every minute. The handover documents list what each alert means and what to do about it.
Need the frontend too? Full stack development covers the whole product. For the wider picture, see custom web app development and our pricing. To talk about your backend, contact us.



