For most of the last decade, the SMM industry has run on a single PHP codebase that gets re-skinned and re-sold by hundreds of operators. Rather than launch yet another fork of it, we built NotPanel from scratch on a modern platform.
This is the engineering story. What we rejected. What surprised us. The choices we'd make again. Some of them might surprise you — they surprised us.
What we rejected
The legacy script most public panels run has well-documented problems. They aren't unique to any one deployment — they're industry-wide:
- Float-based money. Account balances stored as MySQL
FLOAT. Cumulative drift on high-volume accounts ran into pennies per month. Sounds harmless until you trace it across a multi-year history. - No row-level locks on debits. Two parallel orders against a $10 balance with two $6 charges could both succeed. The fix exists in the codebase but is gated behind config flags most deployments never enable.
- Cron-driven order processing. A PHP script ran every minute, looked for pending orders, forwarded them. The script could miss an order if it crashed mid-run. Or process the same order twice if scheduling overlapped.
- No webhook signing. Outbound webhooks were plain POSTs. Anyone who guessed a customer's webhook URL could fabricate completion events and trigger their downstream logic.
- Plain-text provider keys. Provider API credentials sat as plain VARCHARs in MySQL. A single database dump exposed every upstream relationship.
The principles we picked
We started with a short list of outcomes the rebuilt product had to provide:
- Account balances must stay accurate when several requests arrive together.
- Retries must not create duplicate orders or duplicate charges.
- A cancelled order must not be sent for fulfilment afterward.
- Public pages must be fast, indexable, and useful on slow connections.
- Customers and API users should see the same order and balance state.
Those principles led to a product with a few deliberately boring guarantees:
- Pricing is authoritative. The amount charged comes from the current service configuration, never from a price supplied by a browser or API client.
- Balance changes are immediate. A submitted order reserves its full charge immediately, and a valid grace-window cancellation returns it immediately.
- Every important action is retry-safe. A timeout may require a status check, but repeating the same request does not silently create a second financial action.
- Background failures stay visible. Orders keep a clear status, recoverable work can be retried, and unrecoverable cases are surfaced for review instead of disappearing.
- Security-sensitive changes are auditable. Administrative and account actions have clear authorization boundaries and a reviewable history.
Money safety is a product behaviour
Customers should not need to understand our implementation to know what happens to their money. The visible contract is simple:
- The current service and quantity determine the charge.
- An order is accepted only when the available balance covers that charge.
- The accepted charge appears on the wallet immediately.
- A valid cancellation returns the same charge immediately.
- Every debit and refund appears in the account transaction history.
That contract matters more than any implementation diagram. It is also what our automated concurrency and retry tests are written to verify.
One owner for every external action
External actions are where retries become dangerous. If two attempts both believe they own the same order, a customer can be charged once while fulfilment happens twice. We designed order submission, payment handling, and webhook delivery so only one attempt can own a particular action and later attempts safely observe the result.
The important part for users is the outcome: duplicate attempts do not produce duplicate side effects, and a cancellation that wins the grace window is not sent upstream later.
Idempotency as a contract
API order placement supports caller-supplied idempotency keys. That lets an integration retry after a network timeout and receive the original result instead of creating another order. The exact request and response rules live in the public API documentation.
A safe retry should return the same outcome, not create a second financial action.
What's the single most underrated discipline in money-handling code?
What we'd do differently
- Write the financial behaviour tests first. The most valuable tests describe what users can observe during simultaneous orders, retries, and cancellations. Those should have led the implementation from day one.
- Add operational visibility earlier. A clear error with enough context is cheaper than reconstructing a silent failure from customer reports.
- Keep public contracts separate from internal details. Users and integrators need stable behaviours and documented interfaces, while internal implementation choices should remain free to change.
- Review accessibility alongside the first design. Labels, keyboard paths, focus states, and readable errors are much easier to build in than retrofit.
What surprised us
Biggest surprise: customers notice reliability even when they never see the work behind it. Immediate balance updates, predictable retries, clear order states, and useful errors are all part of the user-facing product.
Second surprise: simple contracts beat impressive architecture descriptions. A customer cares that a cancelled order is refunded once and stays cancelled; an integrator cares that a retry is safe. Those promises are concrete and testable.
Open questions we're still figuring out
The platform isn't done. Things we're still iterating on:
- How to make service quality and availability easier to compare before an order is placed.
- How to explain provider degradation and recovery without overwhelming customers with operational noise.
- How to expand translations while ensuring every indexed language has genuinely reviewed content rather than an English fallback.
If you're an engineer evaluating SMM panels — or anyone curious about how a niche category gets modernised — that's the story so far. The platform is open for use at notpanel.com. API documentation lives at /developers. Product and engineering lessons continue to land on this blog as we ship them.