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?
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...)