Enhancing DX by Using Staging Services in Development

Complexity as You Grow When starting with the MVP (Minimal Viable Product) of your startup, your repository is small, typically with one backend and one frontend. Initially, you'll have limited code files, endpoints, pages, dependencies, and services. However, as your startup grows, so will everything—files, endpoints, pages, dependencies, and services. This growth can slow down your compilation, bundling, and feedback loop during development, and increase CPU and memory usage as external services accumulate. Staging for Backend Services A key optimization is to move all services to a staging environment and have all developers use the same services locally—like MongoDB, Elasticsearch, Redis, and others. This ensures consistency while reducing local overhead. Isolating Work for Specific Endpoints Rather than running the entire application, developers typically focus on specific endpoints or services. Why not let them work on just those parts without the need to run the whole project? Here's an example of how to achieve this: export const getDevKoaApp = (router): Koa => { const app = new Koa({ proxy: true, // we are behind a proxy keys: [process.env.JWT_KEY], // used for cookies sign }); // add koa middleware // use router that will be used to run local code app.use(router.routes()).use(router.allowedMethods()); // proxy all the other requests to staging app .use(routerStagingProxy.routes()) .use(routerStagingProxy.allowedMethods()); } getDevKoaApp receives a router with only the endpoints the developer is working on. routerStagingProxy forwards any requests not handled locally to the staging environment. Here's the implementation of routerStagingProxy: routerStagingProxy.all( '/(.*)', async (ctx, next) => { const url = `${staging}${ctx.request.path}`; // eslint-disable-next-line console.log('proxying to staging: ', url, ctx.request.method); if (ctx.request.body?.operationName) { // eslint-disable-next-line console.log(ctx.request.body?.operationName); } await next(); }, koaProxy2({ host: staging, suppressRequestHeaders: forbiddenHeaders, logLevel: 'debug', secure: false, changeOrigin: true, onProxyReq(proxyReq, ctx) { for (const header of forbiddenHeaders) { proxyReq.removeHeader(header); } }, }), ); This setup forwards all endpoints that aren’t running locally to staging. Staging for Frontend Services For frontend services, you can just define the apiBaseUrl that will forward the request from local to staging We are using Rspack for his. devServer: { proxy: [ { context: ['/console'] secure: false, changeOrigin: true, cookieDomainRewrite: 'localhost', target: apiBaseUrl, onProxyReq: (proxyReq) => { // Browers may send Origin headers even with same-origin // requests. To prevent CORS issues, we have to change // the Origin to match the target URL. if (proxyReq.getHeader('origin')) { proxyReq.setHeader('origin', apiBaseUrl); } }, } ] } Why Forward Services to a Staging Environment? Developing locally against a staging environment has several advantages: Access to Real Data: You can test features with near-production data without replicating databases or APIs locally. Consistent Environment: Avoid issues where "it works on my machine" but fails in staging due to environment differences. Faster Iterations: Skip the setup time for heavy services locally, focusing instead on core application logic. Summary As your product scales, adding more services, endpoints, and frontends can overwhelm your developers. Forwarding services from local to staging provides a seamless developer experience—developers can work locally as if they’re running everything, without the overhead of managing all services. How are you scaling your codebase as your product grows? Let me know! Woovi Woovi is a fintech platform revolutionizing how businesses and developers handle payments in Brazil. Built with a developer-first mindset, Woovi simplifies integration with instant payment methods like Pix, enabling companies to receive payments seamlessly and automate financial workflows. If you want to work with us, we are hiring! Photo by Nastya Dulhiier on Unsplash

Jan 22, 2025 - 13:20
 0
Enhancing DX by Using Staging Services in Development

Complexity as You Grow

When starting with the MVP (Minimal Viable Product) of your startup, your repository is small, typically with one backend and one frontend. Initially, you'll have limited code files, endpoints, pages, dependencies, and services. However, as your startup grows, so will everything—files, endpoints, pages, dependencies, and services. This growth can slow down your compilation, bundling, and feedback loop during development, and increase CPU and memory usage as external services accumulate.

Staging for Backend Services

A key optimization is to move all services to a staging environment and have all developers use the same services locally—like MongoDB, Elasticsearch, Redis, and others. This ensures consistency while reducing local overhead.

Isolating Work for Specific Endpoints

Rather than running the entire application, developers typically focus on specific endpoints or services. Why not let them work on just those parts without the need to run the whole project? Here's an example of how to achieve this:

export const getDevKoaApp = (router): Koa => { 
   const app = new Koa({
    proxy: true, // we are behind a proxy
    keys: [process.env.JWT_KEY], // used for cookies sign
  });

  // add koa middleware

  // use router that will be used to run local code
  app.use(router.routes()).use(router.allowedMethods());

  // proxy all the other requests to staging
  app
    .use(routerStagingProxy.routes())
    .use(routerStagingProxy.allowedMethods()); 
}

getDevKoaApp receives a router with only the endpoints the developer is working on.
routerStagingProxy forwards any requests not handled locally to the staging environment.

Here's the implementation of routerStagingProxy:

routerStagingProxy.all(
  '/(.*)',
  async (ctx, next) => {
    const url = `${staging}${ctx.request.path}`;

    // eslint-disable-next-line
    console.log('proxying to staging: ', url, ctx.request.method);

    if (ctx.request.body?.operationName) {
      // eslint-disable-next-line
      console.log(ctx.request.body?.operationName);
    }
    await next();
  },
  koaProxy2({
    host: staging,
    suppressRequestHeaders: forbiddenHeaders,
    logLevel: 'debug',
    secure: false,
    changeOrigin: true,
    onProxyReq(proxyReq, ctx) {
      for (const header of forbiddenHeaders) {
        proxyReq.removeHeader(header);
      }
    },
  }),
);

This setup forwards all endpoints that aren’t running locally to staging.

Staging for Frontend Services

For frontend services, you can just define the apiBaseUrl that will forward the request from local to staging

We are using Rspack for his.

devServer: {
  proxy: [
  {
    context: ['/console']
    secure: false,
    changeOrigin: true,
    cookieDomainRewrite: 'localhost',
    target: apiBaseUrl,
    onProxyReq: (proxyReq) => {
      // Browers may send Origin headers even with same-origin
      // requests. To prevent CORS issues, we have to change
      // the Origin to match the target URL.
      if (proxyReq.getHeader('origin')) {
        proxyReq.setHeader('origin', apiBaseUrl);
      }
    },
  }
 ] 
}

Why Forward Services to a Staging Environment?

Developing locally against a staging environment has several advantages:

  1. Access to Real Data: You can test features with near-production data without replicating databases or APIs locally.
  2. Consistent Environment: Avoid issues where "it works on my machine" but fails in staging due to environment differences.
  3. Faster Iterations: Skip the setup time for heavy services locally, focusing instead on core application logic.

Summary

As your product scales, adding more services, endpoints, and frontends can overwhelm your developers. Forwarding services from local to staging provides a seamless developer experience—developers can work locally as if they’re running everything, without the overhead of managing all services.

How are you scaling your codebase as your product grows? Let me know!

Woovi
Woovi is a fintech platform revolutionizing how businesses and developers handle payments in Brazil. Built with a developer-first mindset, Woovi simplifies integration with instant payment methods like Pix, enabling companies to receive payments seamlessly and automate financial workflows.

If you want to work with us, we are hiring!

Photo by Nastya Dulhiier on Unsplash

What's Your Reaction?

like

dislike

love

funny

angry

sad

wow