iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
FoxyInvoice’s Chapter 3 describes one codebase deployed as two separately configured products: a static Angular app, a .NET API, background workers and a Postgres database for each deployment, all behind Caddy. The author’s guiding test is whether one operator can keep the system running at 2 a.m.—a practical constraint that shapes the choices more than any stated scale target. This is the author’s account of the system, not an independent audit of its code or production operation.
What the architecture looks like
The chapter describes a browser-facing app and two server-side processes, with Caddy at the edge. The frontend handles the user interface; the API handles domain operations; workers take on slower or retryable work. Each product deployment reportedly runs its own Postgres instance.
- Frontend: Angular 22 with Material, compiled into static files and served by Caddy. The author describes it as an installable progressive web app with an offline app shell and branding selected at runtime for each deployment.
- API: .NET 10, described as stateless and responsible for domain logic. Caddy serves the app and reverse-proxies
/api/*requests to the API. - Worker: A separate containerized entry point into the same codebase. It handles email delivery, reminders, recurring invoice generation and lead-radar tasks so that slower work does not hold up invoice requests.
The chapter also names SES for email, S3 for files, Stripe for payments, and GitHub Actions over SSH for deployment. These are components in the author’s reported setup, not endorsements or independently verified details. Framework versions and implementation descriptions here are those given in the chapter, rather than a separate check of current releases.
Why use familiar, separated pieces?
The author frames the design around the question, “can one tired person run this at 2 a.m.?” The chapter says Angular was chosen because the operator already knew it, and .NET because it was familiar, documented and strongly typed. A separate worker gives slow or retryable tasks a place to run outside the request path. The case for these choices is operational familiarity and separation of responsibilities, not a benchmark showing that they outperform alternatives.
#1 Best Overall
- This value 3 pack of Adams Invoice Books give you 150 two part carbonless invoices with a perforated white customer receipt and yellow duplicates for your records; 3 50-invoice books per pack
- Unique horizontal invoice sheets capture the purchased by and shipped to addresses; a compact 5-9/16 x 8-7/16 page still leaves plenty of room for details on up to 12 items sold
- Wraparound back cover prevents write-through between sets; pull out the perforated white customer receipt and the yellow carbonless duplicates stay behind for your records
- Unique 6 digit invoice numbers help you thumb through orders quickly; blank space up top gives you room for a company stamp—an affordable custom touch
- In value packs with three 50-invoice books for your small business; buy ahead to keep on site or take on the road for pop-up shop sales
Keep operations testable and typed
In the described API, controllers pass command or query records to an in-process dispatcher, with one handler for each operation. The author says this arrangement allows handlers to be unit-tested without starting a web server, gives request shapes compiler-checked types, and places validation, logging and transactions in a pipeline.
The chapter also recounts a production crash loop caused by a MediatR version conflict, followed by replacing the library in an afternoon. That is the author’s account of one incident, not an independently confirmed reliability finding. It illustrates a trade-off: a library can make a familiar pattern convenient, but its dependency and versioning still become part of the system an operator must maintain.
Rank #2
- QUALITY INVOICES: Adams Invoice books provide a professional invoice or customer receipt; easily customize by using the extra space at the top and your company stamp
- 50-TWO PART CARBONLESS FORMS: Customers get the perforated white top copy; retain the yellow copy for your records
- WRAP-AROUND COVER: Fold the back cover between sets to keep invoices neat and legible
- CONSECUTIVELY NUMBERED: Large 6-digit numbers help you thumb through invoices quickly
- STOCK UP: Each book includes 50 white/canary sets; order several to keep your favorite forms on hand
How the outbox separates saving from sending
If an API saves an invoice and then tries to send email synchronously, the email provider can fail after the invoice is already committed. The caller may see an error even though the business record exists, and a retry can create confusion about what happened. The chapter’s transactional outbox addresses that split by recording the business change and the work to be done in one database transaction.
- The application writes the business record, such as an invoice change, and a corresponding row in
outbox_messageswithin the same transaction. - After commit, a worker repeatedly checks for unsent messages and attempts delivery.
- On success, the worker marks a message sent; on failure, it retries and records an error, as described by the chapter.
The author says invoice sends, reminders and feedback notifications use this flow. Its practical promise is that the user’s action is durable once the transaction commits, while delivery happens asynchronously. A committed outbox entry is not the same as a guarantee that a recipient received an email: the chapter describes retries and recorded state, but does not specify a complete delivery-semantics design.
Rank #3
- Custom 2 Part Carbonless Invoice Book Personalize your custom carbonless invoice book with your business logo, company name, phone number, address, invoice number, payment terms, service details, or custom text for professional small business records.
- Practical Carbonless Forms 2 part carbonless pages make it easy to write once and create duplicate copies for customers, office records, service records, estimates, and payment receipts.
- Duplicate Receipt Forms for Daily Use 2 part carbonless receipt forms create a customer copy and a business copy without separate carbon paper, making them practical for invoices, receipts, work orders, estimates, quotes, sales orders, and service records.
- Professional Custom Business Forms Clear printing, organized layout, smooth writing paper, and practical form sections help present your business information clearly. Suitable for customer payments, repair records, job details, sales tracking, and office filing.
- Bulk Custom Orders & Support Great for bulk custom invoice books, company teams, contractor groups, service crews, business branches, and promotional business supplies. We provide helpful support for artwork, customization details, order questions, or after-sales solutions.
How the domain model handles invoices and money
The chapter describes a tenant-oriented model connecting tenants to users and clients, clients to invoices, and invoices to line items. Totals are recomputed server-side from line items when an invoice is changed, rather than relying on a submitted client-side total.
For amounts, the author uses a Money value that carries both a decimal amount and a currency. Its addition and subtraction operations reject mismatched currencies instead of silently treating different currencies as interchangeable. In the reported implementation, EF Core maps this value through a complex type to numeric(18,2) and char(3) database columns. Those are implementation choices in this system, not a general accounting rule or a complete treatment of every currency’s precision requirements.
Rank #4
- QUALITY INVOICES: Adams Invoice books provide a professional invoice or customer receipt; easily customize by using the extra space at the top and your company stamp
- 50-TWO PART CARBONLESS FORMS: Customers get the perforated white top copy; retain the yellow copy for your records
- SPIRAL BOUND EFFICIENCY: A neat spiral keeps your duplicates in chronological order for a permanent record of all invoices
- CONSECUTIVELY NUMBERED: Large 6-digit numbers help you thumb through orders quickly
- 50 SETS PER BOOK: Each book provides 50 2-part carbonless forms
The chapter lists invoice states as Draft, Sent, Paid, Partial, Overdue and Void. A Quote is represented as a type that can be cloned into an invoice. These are descriptions of the application’s domain model, not legal or accounting guidance.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →How one codebase reportedly serves two products
The author says foxyinvoice.com is a freemium, fox-branded product with Stripe enabled, while invoices.seolith.com is an enterprise-branded deployment used for the author’s own books. Both reportedly use the same Docker images and single-page-app bundle, but are deployed separately with different environment configuration.
Best Value
- 2-part billing form
- Carbonless with white original and canary duplicate
- Book size: 8 1/2 x 8 1/4 inches
- Detached size: 8 1/2 x 7 3/4 inches
- Convenient spiral bound booklet
This arrangement means a code fix can be shipped to both deployments without maintaining separate application code. It also gives the author a way to use the system in a second setting. The trade-off the chapter identifies is multi-tenancy from day one: shared code does not remove the need to keep each tenant’s data and behavior appropriately separated. The chapter offers no measured cost or performance comparison, so its characterization of another deployment as “one more docker compose project” should not be read as an operating-cost estimate.
Why prerender public pages?
The author says ordinary client-side-rendered routes can be difficult for crawlers that do not execute JavaScript, while full server-side rendering would introduce another server to operate. The chosen middle ground is build-time prerendering: marketing routes are generated as static pages and served through Caddy, while ordinary users receive the app.
The chapter says those pages include titles, descriptions, canonical tags, JSON-LD and article text. This explains the author’s implementation rationale, but the chapter does not provide independent crawl tests or comparative SEO results.
What this case study does—and does not—show
The architecture is best understood as a set of operator-focused choices in one reported system: static delivery for the frontend, an API for domain operations, a worker boundary for asynchronous tasks, and an outbox that records work alongside business changes. Currency-aware arithmetic makes one category of invalid operation explicit, while two deployments allow shared code to serve distinct configurations.
It is not evidence that this stack is the best choice for every billing product, that the two deployments have equivalent performance, or that the described services and versions remain unchanged. The value of the chapter is more specific: it shows how one author organizes a billing application around maintainability and the realities of operating it with limited hands.
Quick Recap
Read the DEV Community chapter
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

