A Bank Wanted to Use AI to Approve Loans Faster, Here Is What I Would Build Around It in NestJS
A Bank Wanted to Use AI to Approve Loans Faster, Here Is What I Would Build Around It in NestJS
一家银行想用 AI 加速贷款审批,以下是我在 NestJS 中构建的配套方案
A loan officer at a small digital bank was excited about the new model the data team had built. It could score a loan application in under a second, based on income, spending patterns, and repayment history, and approve or reject it automatically. The first week it ran, it worked beautifully. The second week, the model provider had an outage in the middle of the afternoon. Every loan application submitted during that window just hung, waiting on a response that was never coming. Some customers refreshed the page and submitted twice. A few applications that should have been rejected outright ended up approved, because a fallback path someone had written months earlier, and never tested properly, defaulted to approving anything it could not score. 一家小型数字银行的信贷员对数据团队构建的新模型感到非常兴奋。该模型能根据收入、消费模式和还款记录,在不到一秒钟的时间内对贷款申请进行评分,并自动批准或拒绝。运行的第一周,效果非常理想。到了第二周,模型提供商在下午发生了一次故障。在那段时间内提交的所有贷款申请都处于挂起状态,等待着永远不会到来的响应。一些客户刷新页面并重复提交。由于几个月前有人编写且从未经过妥善测试的后备路径(fallback path)默认将无法评分的申请一律批准,导致一些本应被直接拒绝的申请最终被批准了。
Nobody on the data team had done anything wrong with the model itself. The model was accurate. What was missing was everything around it, the part that decides what happens when the model is slow, wrong, unavailable, or simply not something you should trust blindly with a decision this big. 数据团队在模型本身上并没有做错任何事。模型是准确的。缺失的是模型周围的一切——即当模型运行缓慢、出错、不可用,或者仅仅是不值得在如此重大的决策上盲目信任时,决定该如何处理的那部分逻辑。
The real problem is never the model. A bank does not really have an AI problem when it adopts a model for something like loan approval or fraud scoring. It has an integration problem. The model is a service you call, and like any service, it can be slow, it can fail, and it can be confidently wrong. The question that matters is not whether the model is smart. It is what the backend does the moment the model does not behave the way everyone assumed it would. 真正的问题从来不是模型本身。当银行采用模型进行贷款审批或欺诈评分时,它面临的并不是 AI 问题,而是集成问题。模型是你调用的一个服务,像任何服务一样,它可能会变慢、可能会失败,也可能会“自信地出错”。真正重要的问题不是模型是否聪明,而是当模型表现不如预期时,后端该如何应对。
Enforcing a timeout so a slow model cannot freeze the whole flow
强制执行超时,防止缓慢的模型冻结整个流程
The first guardrail is making sure a call to the model can never hang indefinitely. If the model provider is slow or down, the request should fail fast and fall back to a safe default, not leave the customer staring at a loading screen. 第一道防线是确保对模型的调用永远不会无限期挂起。如果模型提供商运行缓慢或宕机,请求应该快速失败并回退到一个安全的默认状态,而不是让客户盯着加载界面干等。
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { firstValueFrom, timeout, catchError } from 'rxjs';
@Injectable()
export class LoanScoringService {
constructor(private readonly httpService: HttpService) {}
async scoreApplication(applicationId: string, payload: Record<string, unknown>) {
return firstValueFrom(
this.httpService.post('https://ai-provider.example.com/score', payload).pipe(
timeout(2000),
catchError(() => {
throw new HttpException(
'Scoring service unavailable',
HttpStatus.SERVICE_UNAVAILABLE,
);
}),
),
);
}
}
Notice that the fallback here is an explicit error, not a silent approval. Whatever happens next, defaulting to approving a loan because a service call failed is never an acceptable behavior on its own. 请注意,这里的回退是一个明确的错误,而不是静默批准。无论接下来发生什么,仅仅因为服务调用失败就默认批准贷款,这在任何情况下都是不可接受的行为。
Deciding what fail safe actually means for a loan decision
确定贷款决策中“故障安全”的真正含义
Once a timeout or failure is caught, something has to happen next, and for a decision this significant, that something should never be an automatic approval. A sensible fail safe path is to route the application to a manual review queue instead. 一旦捕获到超时或故障,必须采取后续行动。对于如此重大的决策,后续行动绝不应该是自动批准。一个合理的故障安全路径是将申请转入人工审核队列。
async handleScoringFailure(applicationId: string) {
await this.reviewQueueService.enqueue({
applicationId,
reason: 'scoring_service_unavailable',
requiresManualReview: true,
});
return {
status: 'pending_review',
message: 'Your application is being reviewed manually.',
};
}
This keeps the customer informed honestly, and it makes sure a technical failure never quietly turns into a financial decision nobody actually made on purpose. 这能诚实地告知客户,并确保技术故障不会悄无声息地演变成一个无人刻意做出的财务决策。
Logging every decision so it can be explained later
记录每一项决策以便日后追溯
A bank will eventually need to explain why a specific customer was approved, rejected, or flagged, sometimes months later, sometimes to a regulator. That means every scoring decision, along with the model’s output and the data it was based on, needs to be recorded, not just acted on and discarded. 银行最终需要解释为什么某个特定客户被批准、拒绝或标记,有时是在几个月后,有时是向监管机构解释。这意味着每一项评分决策,连同模型的输出和所依据的数据,都需要被记录下来,而不是执行完就丢弃。
import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn } from 'typeorm';
@Entity('loan_decisions')
export class LoanDecision {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
applicationId: string;
@Column({ type: 'jsonb' })
modelInput: Record<string, unknown>;
@Column({ type: 'jsonb' })
modelOutput: Record<string, unknown>;
@Column()
finalDecision: string;
@Column({ default: false })
requiredManualReview: boolean;
@CreateDateColumn()
createdAt: Date;
}
With this in place, a decision made in under a second can still be fully reconstructed and explained later, which matters far more in banking than in almost any other kind of application. 有了这些,即使是在不到一秒钟内做出的决策,日后也能被完整还原和解释。在银行业,这一点比几乎任何其他类型的应用都更为重要。
Keeping a human in the loop for the decisions that matter most
在最关键的决策中保持人工参与
Not every decision needs a person reviewing it, but the ones with real consequences, a large loan amount, a borderline score, a customer disputing a rejection, should never be finalized by the model alone. NestJS gives you a clean place to enforce that gate, a check that routes certain outcomes to a review queue instead of directly to the customer, based on rules the bank actually agrees with, rather than whatever the model happened to output. 并非每一项决策都需要人工审核,但那些具有实际后果的决策——如大额贷款、临界评分、客户对拒绝结果提出异议等——绝不应仅由模型决定。NestJS 为你提供了一个清晰的场所来执行这一关卡:根据银行认可的规则(而非模型碰巧输出的结果),将特定结果路由到审核队列,而不是直接反馈给客户。
The bigger picture
宏观视角
NestJS does not make an AI model more accurate, and it never should try to. What it gives you is the structure around the model, a place to enforce timeouts, a place to decide what fail safe actually means, a place to log every decision so it can be explained later, and a place to insist a person reviews the decisions that deserve one. That structure is what actually makes an AI model safe enough to use for something as consequential as approving a loan. NestJS 不会提高 AI 模型的准确性,也不应该尝试这样做。它为你提供的是模型周围的结构:一个强制执行超时的地方,一个定义“故障安全”含义的地方,一个记录每一项决策以便日后解释的地方,以及一个确保重要决策必须经过人工审核的地方。正是这种结构,才使得 AI 模型在贷款审批这样重大的事务中足够安全。
If your team is bringing AI into a process that touches real money or real customers, I would be glad to talk through how to build the guardrails around it properly. 如果你的团队正在将 AI 引入涉及真实资金或真实客户的流程中,我很乐意与你探讨如何正确地构建配套的防护措施。
I am Peace Melodi, a backend software engineer. If you want your business to scale big, comfortably handling millions of users without breaking, with strong scalability and security in place, feel free to reach out. 我是 Peace Melodi,一名后端软件工程师。如果你希望你的业务能够大规模扩展,在处理数百万用户时依然稳健,并具备强大的可扩展性和安全性,欢迎随时联系我。
LinkedIn: https://www.linkedin.com/in/melodi-peace-406494368 GitHub: https://github.com/PeaceMelodi