Back to blog

Greenfield microservices with Go & Java 21: from DDD to production

Starting from a blank canvas is both the most exciting and most dangerous position in software engineering. With no legacy to constrain you, every architectural decision you make in the first few weeks will shape the platform for years. This post covers how we approach greenfield platform incubation at CloudPrimacy — the decisions we make early, why we make them, and how we get from whiteboard to production-grade delivery.

Start with the domain, not the technology

The single most common mistake on greenfield projects is reaching for a tech stack before the domain is understood. We spend the first engagements doing event storming and domain modelling — identifying bounded contexts, aggregates, and the language the business actually uses. The technology follows the domain shape, not the other way around.

On a recent fintech platform, the domain model surfaced four natural bounded contexts: identity, accounts, transactions, and notifications. Each became its own service, owned by a sub-team, with a well-defined contract at the boundary. That clarity upstream made every downstream technical decision easier.

Why Go for some services, Java 21 for others

We don't have a religion about language choice — we match the language to the workload characteristics:

The key is making the choice deliberately and documenting the reasoning — so future engineers understand the intent rather than guessing.

Architecture principles we apply consistently

Regardless of language, we apply a consistent set of principles across every service:

Infrastructure: Terraform from the start

We provision everything with Terraform. No console-click infrastructure, ever. This isn't dogma — it's practical: it makes environments reproducible, drift detectable, and onboarding new engineers fast. We structure Terraform into modules per bounded context, with a shared networking and IAM foundation layer. State is remote (S3 + DynamoDB locking) from day one.

On AWS, our standard greenfield stack is: ECS Fargate for services that need persistent compute, Lambda for event-driven workloads, API Gateway for external-facing endpoints, RDS Aurora Serverless or DynamoDB depending on the data shape, and CloudFront + S3 for static frontends.

CI/CD: ship from day one

We set up CI/CD pipelines before writing the first line of application code. GitHub Actions with environment-specific workflows: PR builds run tests and linting, merges to main deploy to staging automatically, and production deployments require a manual approval gate. Docker images are built, tagged with the Git SHA, and pushed to ECR. No "we'll sort the pipeline out later" — later never comes.

Blue/green deployments via ECS allow zero-downtime releases. Feature flags (we use a lightweight SSM Parameter Store pattern rather than a third-party service for most cases) allow safe incremental rollout of new functionality.

Frontend: Next.js on the edge

For customer-facing frontends we use Next.js — server-side rendering for SEO-critical pages, static generation for content, and React for interactivity. Deployed to CloudFront + S3, with ISR (Incremental Static Regeneration) where content changes frequently. TypeScript throughout, Tailwind for styling, and a strict component library contract between design and engineering.

What we've learned

A few things that still surprise teams coming to greenfield work for the first time:

Greenfield is a privilege. The blank canvas only stays blank for a few weeks — make those weeks count. If you're embarking on a new platform and want an experienced engineering lead in the room from day one, get in touch.

Build with CloudPrimacy

Starting a new platform? We embed as engineering leads from day one.

Get in touch