We have a microservices architecture very similar to the architecture described here

microservice architecture

Obviously, it's a simplified diagram of a real system. In our case, we have a requirement to perform background operations in a service in addition to exposing APIs. e.g.

  • In the Catalog service, if a certain product's count goes below a threshold, a notification needs to be sent to fulfillment team
  • In the Customer service, if a customer has not logged in for x days (and opted for promos), a promo email needs to be sent

Now my question is: should these background jobs be their own microservices (with own executable and own database) or will be another executable in the same microservice? For example with the latter approach, Customer service will comprise of CustomerAPI and CustomerPromoJob and share the same database. Is that an anti-pattern as all the applications in the Customer service will have to be deployed at the same time?


It's a fairly common need to have background processes that work against a single micro-service sized chunk of data alongside an API - especially in environments that use data buses or message queues to buffer things that can be eventually consistent. And it can be desirable to host them alongside the actual API so there's less chance of partial deployment failure.

That said, they need to be cohesive enough that your microservices are still focused on a single responsibility with a tiny data scope. And running them all together can cause performance, monitoring, security, and operations trouble.

So as with most things, it depends. There are tradeoffs for either approach, and you should maybe err towards keeping them as separate services, but there are common scenarios where it is good to bundle them.

  • If it's two applications, would you consider both of them sharing the same database as an anti+pattern?
    – ubi
    Dec 28 '18 at 7:26
  • Absolutely, because then they are not independently deplorable and not microservices.
    – Telastyn
    Dec 28 '18 at 15:20

Well designed software is easy to change

Anything that you do that makes it harder for you to change this system is by definition not well designed.

Without knowing much about the deployment infrastructure, having to deploy two different packages that directly use the same database schema makes them tightly coupled and therefor requires two things to be tested even if only one is changing. This makes change harder.

If instead only one package was deployed then another source of friction is the difference between API and Batch. The API usually requires dynamic, fast, individual record updates, while the Batch works best with long running bulk record updates. You may be able to make the batch work as an API driver. This will work for low volumes early on, but will become problematic with higher volumes. In short the data life-cycle of these two processes are very different. Constraining them to a single schema will cause issues, making change harder.

The most sensible action would be to separate these processes completely. I would suggest a Customer Notification Service. Its sole goal is to manage notification via whatever customer preferred means. It would receive as either a data-dump, or via some sort of event log additions/cancellations from the other services. As a healthy aside this serves a direct business need: How is the business engaging a given customer?

Batch/API Fusion

There are instances where it does make sense to have the same program operate as both an API and a batch process. Programs such as Jenkins, or Fossil SCM: export Web Front ends, and APIs; while providing batch style processing.

The difference is that the same "Service" is being provided by each interface , even if each interface is being provided by a separate process.

Change will have to happen to all interfaces in (near) lock-step with each other. If each interface were provided by a separate self-contained service in separate code bases then such a change would have to be performed once per interface. Any defects detected in one project will need to be verified across all (to ensure consistency). This makes for a lot of work for each change.

Comparatively having a single code-base can significantly reduce both implementation and maintenance time with each added interface. For this to be a contender though several properties are required:

  • the domain logic needs to be shareable and if duplicated easily verified as being consistent by common implementation agnostic feature tests.
  • The interfaces need to provide consistent domain behaviours with only a few omitted features (such as new/experimental/deprecated behaviours), and diverge only slightly in terms of interface behaviours (such as paging results, chunked data transfer, data escaping and encoding, etc...)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.