← Back to list

Services Are Not Your Business Layer (And Why That Mistake Scales Poorly)

The Angular Service That Started Innocently

Dipak Ahirav in Angular Engineering · 2026-06-05 16:52 · 0 claps · 4.0 min read paywalled
#angular #software-development #frontend-architecture #typescript #software-engineering
Open on Medium ↗
Wiki topics: 🌐 · Web Development 🏛️ · Architecture

Services Are Not Your Business Layer (And Why That Mistake Scales Poorly)

The Angular Service That Started Innocently

Most Angular services begin their life looking something like this:

@Injectable()
export class CustomerService {

constructor(
    private http: HttpClient
  ) {}
  getCustomers() {
    return this.http.get<Customer[]>(
      '/api/customers'
    );
  }
}

Simple.

Clean.

Easy to understand.

The service acts as a thin wrapper around an API.

Nothing controversial.

Then the application grows.

And that’s when things begin to change.

**Not a Member? Read for FREE here.**

The Slippery Slope

A new requirement arrives.

The customer data needs validation.

So validation gets added.

Then permissions.

Then audit logging.

Then caching.

Then analytics.

Then feature flags.

Then approval workflows.

Eventually the service looks like this:

@Injectable()
export class CustomerService {

validateCustomer() {}
  checkPermissions() {}
  calculateDiscounts() {}
  determineApprovalFlow() {}
  logAuditEvent() {}
  updateCache() {}
  sendAnalytics() {}
  notifyUsers() {}
  saveCustomer() {}
}

The service is no longer a service.

It’s an entire application hidden inside a single file.

Why This Happens

Angular gives us a convenient place to put logic.

That place is called a service.

So whenever developers ask:

Where should this code go?

The answer often becomes:

Put it in the service.

Repeat this enough times and the service becomes the default destination for everything.

The architecture slowly collapses into:

Component
    │
    ▼
Huge Service
    │
    ▼
Everything Else

At first this feels organized.

Eventually it becomes one of the biggest maintenance problems in the codebase.

Services Were Never Meant To Own Business Logic

This is the key misunderstanding.

A service is not a business layer.

A service is simply a technical abstraction.

Examples:

CustomerApiService
NotificationService
StorageService
AnalyticsService
LoggingService

Notice something.

Each service performs a technical responsibility.

They provide capabilities.

They don’t define business processes.

That’s an important distinction.

Business Logic Is Different

Consider a customer approval workflow.

The workflow might be:

Validate Customer
      │
      ▼
Check Permissions
      │
      ▼
Determine Approval Level
      │
      ▼
Save Customer
      │
      ▼
Generate Audit Record

This is not a technical concern.

This is business behavior.

The workflow exists regardless of:

  • Angular
  • APIs
  • Databases
  • Frameworks

Business logic describes how the business operates.

Not how software communicates.

The Problem With God Services

Imagine a service growing for three years.

Ten developers contribute.

New requirements continuously arrive.

Soon the service becomes:

CustomerService
 ├── API Calls
 ├── Validation
 ├── Permissions
 ├── Workflow Rules
 ├── State Updates
 ├── Analytics
 ├── Logging
 ├── Notifications
 ├── Cache Updates
 └── Feature Flags

Now every feature touches the same file.

Merge conflicts increase.

Testing becomes harder.

Understanding behavior becomes difficult.

Changing one workflow risks breaking another.

The service becomes a bottleneck.

What Scalable Architectures Do Instead

Large applications separate responsibilities.

Example:

CustomerPageComponent
        │
        ▼
CustomerFacade
        │
        ▼
CustomerApprovalWorkflow
        │
        ├── CustomerApiService
        ├── AuditService
        ├── NotificationService
        └── PermissionService

Each layer has a specific responsibility.

Components coordinate.

Workflows define business behavior.

Services provide technical capabilities.

The architecture becomes easier to evolve.

A Useful Mental Model

Think of services as tools.

A hammer is useful.

A screwdriver is useful.

A wrench is useful.

But none of those tools define how to build a house.

Similarly:

NotificationService
LoggingService
AnalyticsService

are tools.

They help implement business processes.

They are not the business process itself.

The Facade Layer Changes Everything

Many enterprise Angular applications introduce facades.

Instead of:

Component
      │
      ▼
Huge Service

You get:

Component
      │
      ▼
Facade
      │
      ▼
Workflow Layer
      │
      ▼
Services

This creates a natural separation.

Business decisions stay together.

Technical implementations stay together.

Future changes become easier.

Signals Don’t Solve This Problem

Modern Angular gives us Signals.

Signals simplify state management.

Signals improve reactivity.

Signals reduce boilerplate.

But Signals do not solve misplaced responsibilities.

You can still build a 3,000-line service using Signals.

The underlying architectural mistake remains the same.

Architecture and reactivity solve different problems.

How To Spot A Service That Has Become Too Large

Warning signs include:

  • Hundreds of lines of business rules
  • Multiple unrelated responsibilities
  • Large constructor dependency lists
  • Difficult unit tests
  • Frequent merge conflicts
  • Developers afraid to modify it

When these symptoms appear, the service has likely outgrown its original purpose.

What Senior Engineers Usually Ask

Junior developers often ask:

Where should I put this code?

Senior engineers ask:

Who should own this responsibility?

That question changes everything.

Instead of dumping logic into services, they think about:

  • Business boundaries
  • Ownership
  • Workflows
  • Dependencies
  • Long-term maintainability

This leads to much healthier architectures.

A Practical Rule

Whenever you’re about to add new logic to a service, ask:

Is this technical behavior or business behavior?

If it’s technical:

A service is probably appropriate.

If it’s business behavior:

Consider a workflow layer, facade, store, or domain abstraction.

That small distinction prevents many architectural problems.

Final Thoughts

Angular services are one of the framework’s most useful features.

Unfortunately, they often become victims of their own convenience.

Because services provide an easy place to put code, teams gradually place too much code inside them.

The result is the infamous God Service.

The best Angular architectures treat services as technical capabilities.

Business workflows live elsewhere.

Responsibilities remain clear.

And maintainability remains manageable long after the application has grown.

The goal isn’t to eliminate services.

The goal is to stop asking services to do everything.

[embed]The Real Purpose of Dependency Injection (And Why Most Angular Developers Use It Wrong) Most Angular Developers Learn Dependency Injection in the First Weekmedium.com

Connect with Me

If you enjoyed this post and would like to stay updated with more content like this, feel free to connect with me on social media:

Email: Email me on dipaksahirav@gmail.com for any questions, collaborations, or just to say hi!

I appreciate your support and look forward to connecting with you!


메타데이터
post_id
08c6787d1649
slug
services-are-not-your-business-layer-and-why-that-mistake-scales-poorly-08c6787d1649
url
https://medium.com/angular-engineering/services-are-not-your-business-layer-and-why-that-mistake-scales-poorly-08c6787d1649
canonical_url
https://medium.com/angular-engineering/services-are-not-your-business-layer-and-why-that-mistake-scales-poorly-08c6787d1649
author_url
https://medium.com/@dipaksahirav
status
ok
fetched_at
2026-06-14 11:28:49