Santekno
Projects/Service Decommissioning & Cost Optimization — Fetcher/Ingestor Sunset
Backend / APIArchived

Service Decommissioning & Cost Optimization — Fetcher/Ingestor Sunset

Safely sunset two unused merchant-promotion backend services and an unused Redis cache instance, moved remaining responsibilities to the aggregator service, and refactored the main binary to Clean Architecture — delivering a meaningful monthly and yearly infrastructure cost reduction and a cleaner, more maintainable codebase.

2022-fetcher-decommision · main
# E-Commerce / Promotion & Discounts
$ go -X POST /2022-fetcher-decommision/v1/sync
→ 201 Created
{ "status": "ok" }
publish 2022-fetcher-decommision.synced
Role
Backend Engineer
Timeline
2022
Team
2
Domain
E-Commerce / Promotion & Discounts
Stack
7 tech
Status
Archived
01

Overview

This project sunset two unused backend services — a fetcher and an ingestor — inside the merchant-promotion domain, removed an unused Redis cache instance tied to merchant promotion, and refactored the main binary to Clean Architecture. The products those services once supported no longer fit current needs, so keeping them running was pure carrying cost. As backend engineer on this cleanup, I owned the audit, the responsibility handover to the aggregator service, and the refactor of the main binary.

A backend has no screens, so its "UI" here is the operational surface: the target architecture after cleanup, the cost dashboards that reflected the sunset, and the pull requests that retired the legacy code.

Architecture — target aggregator-only layout after sunset
Infrastructure cost — monthly & yearly reduction after cleanup
Pull requests — legacy code removal and Clean Architecture refactor
03

Problem & Solution

Problem

The merchant-promotion stack had accumulated legacy: a fetcher service and an ingestor service that no longer served any active product, plus a Redis cache instance that was no longer read from or written to. On top of that, the main binary was structured as a large monolithic struct that mixed concerns and made maintenance hard — new features had to reach into shared internals, and small changes carried outsized regression risk. The result was ongoing infrastructure cost for capabilities that were not being used, and a codebase that was harder than it needed to be to evolve.

Solution

I ran a traffic and dependency audit to confirm the fetcher and the ingestor were genuinely unused, then moved their remaining responsibilities into the aggregator service and deleted the legacy code from the main binary. In parallel, I refactored the main binary to Clean Architecture, splitting it into clear handler, use-case, and repository layers so the aggregator could absorb the leftover responsibilities without inheriting the old coupling. Once readers and writers on the unused Redis instance were confirmed at zero, the two services and the Redis cache were shut down in a staged rollout, translating the cleanup into a meaningful monthly and yearly infrastructure cost reduction for server rentals.

04

Workflow

Three actors interact with the service; the diagrams are written in English to stay consistent across both languages.

flowchart diagram

decommission + refactor

After

metrics

Campaign Ops

Seller Console

Aggregator Service · Clean Architecture

Prometheus / Grafana

Before

Campaign Ops

Seller Console

Fetcher Service

Ingestor Service

Unused Redis · Merchant Promotion

Aggregator Service

Use case interaction — before vs after decommission
sequence diagram
InfrastructureUnused Redis CacheAggregator ServiceIngestor ServiceFetcher ServiceBackend EngineerInfrastructureUnused Redis CacheAggregator ServiceIngestor ServiceFetcher ServiceBackend Engineeraudit traffic (confirm unused)audit traffic (confirm unused)move remaining responsibilitiesrefactor main binary to Clean Architectureverify no readers/writersshut down Fetcher & Ingestorrelease Redis instancecost reduced (monthly & yearly)
Sequence flow — safe sunset & responsibility handover
05

Architecture

flowchart diagram

rpc

metrics

Seller Console

Aggregator Service · Go · Clean Architecture

Handler Layer

Use Case Layer

Repository Layer

Merchant Promotion Tables

Downstream Dependencies

Prometheus / Grafana

Fetcher Service · Ingestor Service · Unused Redis

Target architecture after decommission
Architecture notes

After the sunset, the merchant-promotion domain is served by a single aggregator service written in Go and organized around Clean Architecture: a handler layer for transport, a use-case layer for business logic, and a repository layer for data access against the merchant-promotion tables. The fetcher service, the ingestor service, and the unused Redis cache instance are removed from the topology entirely. Prometheus and Grafana continue to observe the aggregator to confirm that behavior stayed stable after the responsibilities were consolidated.

state diagram

traffic & dependency audit

responsibilities moved to aggregator

main binary refactored to Clean Architecture

readers/writers confirmed zero

services & Redis instance released

monthly & yearly infra cost reduced

identified

audited

handover

refactored

drained

shutdown

savings

Decommissioning lifecycle
06

Features

Decommissioning
  • Sunset of the unused fetcher service
  • Sunset of the unused ingestor service
  • Removal of an unused Redis cache instance tied to merchant promotion
Refactoring
  • Legacy code deleted from the main binary
  • Responsibilities moved into the aggregator service
  • Main binary refactored to Clean Architecture (previously a monolithic `struct` layout)
Operations
  • Traffic and dependency audit before shutdown
  • Staged rollout with observability on the aggregator
  • Meaningful monthly and yearly infrastructure cost reduction
07

Tech Stack

language
Go
framework
Clean Architecture
protocol
RPCHTTP
cache
Redis
observability
PrometheusGrafana
08

Engineering Challenges

01
Confirming the services were truly unused

Two services in the merchant-promotion domain were suspected to be dead, but "suspected" is not enough to shut down production. Fix: an end-to-end traffic and dependency audit — checking callers, scheduled jobs, and cache read/write patterns — before draining and shutting the fetcher, the ingestor, and the associated Redis instance.

02
Untangling a monolithic `struct` in the main binary

The main binary was hard to maintain because business logic, transport, and data access all lived inside a single large `struct`. Fix: refactor the main binary to Clean Architecture — separating handlers, use cases, and repositories — so the aggregator service could absorb the leftover responsibilities without inheriting the old coupling.

03
Turning cleanup into real cost savings

Deleting code alone does not reduce a cloud bill; unused server rentals and cache instances have to actually be released. Fix: coordinate with the infrastructure owners to shut down the decommissioned services and release the unused Redis instance, translating the cleanup into a meaningful monthly and yearly infrastructure cost reduction.

09

Outcomes

cost↓
meaningful monthly & yearly infra cost reduced
2 services
unused services decommissioned
clean-arch
main binary refactored to Clean Architecture
10

Lessons Learned

Retiring code is as valuable as writing new code when the retired code was carrying real infrastructure cost — but the savings only materialize when the underlying servers and cache instances are actually released, not just when the repository shrinks. Refactoring the main binary to Clean Architecture during the same cleanup paid off twice: it made the aggregator a natural home for the leftover responsibilities, and it left the domain in a shape that is easier to extend the next time a product needs to change.

11

Related Santekno Tutorials

Interested in working together?

Order, payment, or high-traffic event pipelines — let's talk architecture and trade-offs.