Building a financial reporting and settlement engine isn't just about accurate computation — it's about traceability, composability, and the ability to reproduce and audit outcomes over time.
If your data originates from smart meters with 15-minute or hourly granularity, and your financial system spans price signals, tariffs, and ownership hierarchies (meter ➝ site ➝ customer), then designing it as a set of composable APIs can bring powerful benefits.
I scribble some thoughts here how I approached this challenge using Rust + Axum, where each logical method in the system — whether computing settlement or exposing raw volumes — everything itself available as an API. This architecture creates both internal cohesion and external transparency.
🧠 The Challenge: Financial Precision at High Granularity
We're working with:
- Time-series meter data: Often 15-min or hourly intervals across months
- Market price feeds: Varying by timestamp and market area
- Tariff Data: May vary by region, time, and meter type
- Tariff Data Updates Stream: As these registered tariffs can have their price factors changing continuously
- Meter Tariff Applicable Updates Stream: Certain meters can have certain Tariffs applied or removed continuously
- Meter Metadata: E.g., whether a meter is producing or consuming energy
- Hierarchical Ownership: Meters belong to sites, which are owned by customers
From these sources, the system must reliably produce:
- Meter-level settlements
- Site-level earnings summaries
- Customer-level financial reports
- Historical tariff applications Reports
- Regulatory and operational Reporting
🧩 The Composability Model: APIs as Building Blocks
Each core unit of logic in the system is exposed as a standalone API. This allows internal services, third-party partners, custom API consuming dashboards, or auditors to access precise computations or trace upstream data paths.
Examples of foundational API units include:
- get_market_prices(market_area, from, to)
- get_meter_volume(meter_id, from, to)
- get_tariffs_for_meter(meter_id, at_time)
- get_tariffs_for_market_area(market_area, at_time)
- get_meter_metadata(meter_id)
These are the base APIs from which higher-order functions are built.
🧮 Settlement APIs: From Day to Month
The key settlement methods also follow this pattern of composability:
- get_meter_settlement_for_a_day(meter_id, date)
Composes market price, volume, tariff, and meter metadata APIs
Calculates net earnings or costs for that day
Returns detailed breakdown and computation trace
- find_meter_settlement_for_a_month(meter_id, month)
Iteratively calls the above day-level function for each day in the month
Aggregates results, ensuring that no computation logic is duplicated
Enables both replayability and caching of daily results if needed
This "bottom-up" design makes it easy to debug or reproduce any monthly report — one only needs to examine the sequence of daily settlements, each of which is itself transparent and testable.
🗺️ Time-Aware Tariffs
Another key aspect is tariff applicability over time:
- get_tariffs_for_meter(meter_id, at_time)
- get_tariffs_for_market_area(market_area, at_time)
This historical querying capability is essential when re-running settlement logic for past months, back-calculating earnings, or responding to regulatory audits. The tariff API understands effective-dating and changes in rate plans, making the system resilient to business rule changes.
🏠 Sites and Meters: Rolling Up the Hierarchy
Meters are grouped under sites — physical locations or logical assets. This adds the next layer of composability:
- get_meters_for_site(site_id)
- get_site_volume_report(site_id, from, to)
- get_site_earnings(site_id, from, to)
The get_site_earnings API internally fetches all meters for the site and invokes the settlement functions for each. This allows:
- Consistent logic across reporting levels
- Reuse of underlying APIs without rewriting aggregation logic
- Flexibility to adapt site structure without changing core computations
👥 Customer Roll-Up: Portfolio-Level Reporting
Sites, in turn, belong to customers — often large entities owning multiple assets. Composability enables seamless escalation of reports:
- get_sites_for_customer(customer_id)
- get_customer_earnings(customer_id, from, to)
- get_customer_tariff_payments(customer_id, from, to)
This structure supports both financial reporting and portfolio analytics, all built from the same underlying API bricks. A regulator or analyst can request data from any layer with the same traceable logic.
⚙️ Why Rust + Axum?
Rust brings:
- Memory safety and concurrency: Crucial for processing large time-series datasets
- Strong type guarantees: Reduces bugs in critical financial computations
- Speed: Allows real-time reporting without offloading to batch jobs unnecessarily
Axum complements this by:
- Encouraging clear routing and modular handler design
- Enabling each logical function to live as a clean, secure endpoint
- Making API-first composability feel natural and expressive
🔍 Benefits of the Architecture
✅ Transparency
Every report — from a single day’s earnings to an annual customer invoice — can be traced through API chains.
✅ Reproducibility
Historical data is easy to replay using the same input calls that produced it. No hidden black-box logic.
✅ Scalability
Each function can be scaled independently, cached, or parallelized as needed.
✅ Debuggability
If something doesn’t add up, it’s easy to inspect intermediate outputs (e.g., which tariff was applied at what time).
✅ Extensibility
New functions like get_emissions_report_for_site or simulate_tariff_change_impact can be composed using the same APIs — no need to start from scratch.
📈 Conclusion
When building a financial reporting and settlement engine from the ground up — especially for metered data — composability is not just an architectural choice; it's a functional necessity.
By ensuring that every critical method is both reusable and externally exposed, the system becomes:
- Easier to test
- Safer to evolve
- More valuable to stakeholders
Rust + Axum provides the perfect canvas for this type of design. It’s fast, reliable, and expressive — letting you focus on composing logic, not fighting infrastructure.
Top comments (0)