逐日AI

面试题库

共 328 题,当前筛选 5 题。

30 天从前端工程师到 Agent 工程师

D9 Redis Streams 消息总线:XADD/XREADGROUP/XACK/XAUTOCLAIM、consumer group、毒消息

  • Redis Streams 和 Kafka 该怎么选?什么情况下 Streams 明显不够用?How do you choose between Redis Streams and Kafka, and when is Streams clearly not enough?
    国内高频海外高频进阶#message-bus#redis-streams#architecture

    分析过程 · 先想清楚再作答

    1. 这题的坏答案是「看数据量」。吞吐从来不是第一判据——单机 Redis 每秒几万条 XADD 毫无压力,绝大多数业务的量级根本碰不到天花板。答成「量小用 Streams、量大用 Kafka」会被认为没做过选型。
    2. 换成两个真正的判据来推:一、这些消息需要保留多久;二、会不会有第二类消费方。生命周期是「执行一次就没用了」、且只有执行层这一个消费方,Streams 完全够用,还省掉一整套运维;需要「三个月内任意时间点重放」、或者同一份数据要同时喂给实时执行、离线数仓、风控三条链路,那就该上 Kafka。
    3. 再补三条结构性差异:Streams 是内存为主、保留全靠你自己 MAXLEN 或 XTRIM,Kafka 是磁盘顺序写、保留几周是常态;Streams 一个组里加多少消费者都行,Kafka 的消费者数受分区数限制,多了就有人空转;顺序保证的粒度不同,Streams 是单条流内有序而组内分配随机,Kafka 是同 key 落同分区、分区内有序。
    4. 然后主动说出那条最能体现深度的话:Redis 的持久化是有损的。AOF 默认每秒刷盘,最坏丢最后一秒的写入;主从异步复制,故障切换时未同步的消息会消失。所以用 Streams 时架构上必须有一个真相之源——本课是 Postgres 的 runs 表,流只是触发器,丢了消息那个 run 还停在 pending,补投任务会把它捡回来。把总线当唯一数据源是最危险的误用。
    5. 结论落成一句可复用的判断:Streams 适合「触发执行」,Kafka 适合「数据管道」。前者的消息是一次性的命令,后者的消息是需要被多方反复读取的事实。
    6. 可以预期的追问:那 RabbitMQ、SQS 呢?答:RabbitMQ 强在复杂路由和延迟队列(Streams 没有原生延迟投递,要自己带「下次可执行时间」重投);SQS 强在零运维,代价是没有回放、也没有严格顺序(FIFO 队列另算)。把判据说成「保留时长、消费方数量、路由复杂度、运维预算」四条,比背产品参数强得多。

    How to reason about it · think before answering

    1. The bad answer is 'it depends on volume'. Throughput is never the first criterion — a single Redis node handles tens of thousands of XADDs per second, and most workloads never approach that ceiling. 'Small volume Streams, large volume Kafka' reads as never having run a real evaluation.
    2. Use two real criteria instead: how long the messages must be retained, and whether a second class of consumer will appear. If a message is useless once executed and the execution layer is the only consumer, Streams is plenty and saves an entire operational surface. If you need replay from any point in the last three months, or the same data must feed real-time execution, an offline warehouse and a risk engine, choose Kafka.
    3. Add three structural differences: Streams is memory-first with retention you enforce yourself via MAXLEN or XTRIM, while Kafka does sequential disk writes and keeps weeks by default; a Streams group takes any number of consumers, while Kafka consumers are capped by partition count and extras idle; ordering granularity differs — Streams orders a single stream but dispatches randomly within a group, Kafka pins a key to a partition and orders within it.
    4. Then volunteer the line that shows real depth: Redis persistence is lossy. AOF fsyncs once per second by default, so the last second of writes can vanish, and replication is asynchronous, so a failover can drop unreplicated messages. Using Streams therefore requires a source of truth elsewhere — here the Postgres runs table, with the stream acting only as a trigger; a lost message leaves the run pending and a sweeper republishes it. Treating the bus as the only datastore is the dangerous misuse.
    5. Land on a reusable rule: Streams suits triggering work, Kafka suits data pipelines. One carries one-shot commands, the other carries facts that many parties re-read.
    6. Expect: what about RabbitMQ or SQS? RabbitMQ wins on complex routing and delayed delivery (Streams has no native delay, you republish with a next-eligible timestamp); SQS wins on zero operations at the cost of replay and strict ordering (FIFO queues aside). Framing the criteria as retention, number of consumers, routing complexity and operational budget beats reciting product specs.

    答题要点

    • 第一判据不是吞吐,是「消息要保留多久」和「会不会有第二类消费方」
    • 只有执行层一个消费方、消息执行完即失效:Streams 够用,且大概率你已经有 Redis,零新增运维
    • 需要长期保留与任意时间点回放、或多条下游链路共用同一份数据:选 Kafka
    • 结构差异:Streams 内存为主、保留靠自己裁剪、组内分配随机;Kafka 磁盘顺序写、按 key 分区且分区内有序、消费者数受分区限制
    • Redis 持久化有损(AOF 每秒刷盘、异步复制),所以真相之源必须是数据库,流只当触发器,靠补投任务兜底
    • 一句话判断:Streams 适合触发执行,Kafka 适合数据管道

    Key points

    • The first criterion is not throughput but retention length and whether a second class of consumer will exist
    • One consumer class and messages that expire on execution: Streams is enough, and you probably already run Redis
    • Long retention with arbitrary replay, or one dataset feeding several downstream pipelines: pick Kafka
    • Structural differences: Streams is memory-first with self-managed trimming and random in-group dispatch; Kafka is sequential-disk, key-partitioned with in-partition ordering, and caps consumers at partition count
    • Redis persistence is lossy (per-second AOF fsync, async replication), so the database must be the source of truth with the stream as a trigger plus a republish sweeper
    • One-line rule: Streams triggers work, Kafka moves data

D12 长期记忆:pgvector、embedding、chunking、memory_search 工具

  • pgvector 和专用向量数据库相比,优劣分别是什么?你会怎么选?How does pgvector compare with a dedicated vector database, and how would you choose?
    国内高频海外高频进阶#vector-database#pgvector#architecture

    分析过程 · 先想清楚再作答

    1. 这题考的是选型判断力,不是产品参数背诵。开口就报「Milvus 支持分布式、Qdrant 过滤更强」是最没有区分度的答法——面试官想知道你按什么判据选,以及你有没有算过运维成本。
    2. 先给三个提问维度,把选型变成可推导的:数据量到什么量级、要不要和业务表在同一个事务里提交、过滤条件复不复杂。这三问能覆盖绝大多数真实场景。
    3. pgvector 的赢面几乎全在后两问上:记忆表和业务表在同一个库,写记忆和更新执行记录可以放进同一个事务;按用户过滤就是普通 where 条件;备份、监控、连接池、迁移工具全部复用。**多一个有状态服务的运维成本,通常比向量检索的性能更早成为瓶颈**——这句话最能体现你上过线。
    4. 再诚实地说它的天花板:单表到千万级向量时 HNSW 索引构建吃内存、写入放大明显,ANN 与元数据过滤的融合不如专用库,水平扩展只能靠 Postgres 自己那一套。不肯说缺点的人会被认为在推销。
    5. 结论要能写死:百万级以内、需要和业务表一起过滤或同事务提交、团队人手紧,用 pgvector;上千万条、检索本身就是主要负载、有专人维护,上专用库。别在第一天就选专用库。
    6. 可以预期的追问:以后想换库,迁移成本大不大?答案会让很多人意外——换库不用重算 embedding,向量是模型产出的,跟存它的库无关,导出导入即可,成本主要在双写和灰度。真正要全量重算的是换 embedding 模型,那才是硬锁定。

    How to reason about it · think before answering

    1. This is a judgment question, not a feature-recital. Opening with 'Milvus does sharding, Qdrant filters better' carries no signal — they want your decision criteria and whether you have priced the operational overhead.
    2. Offer three questions that make the choice derivable: what scale, does it need to commit in the same transaction as business tables, and how complex is the metadata filtering.
    3. pgvector wins on the last two: memories live in the same database as the business tables, so writing a memory and updating a run share one transaction; filtering by user is an ordinary WHERE clause; backups, monitoring, pooling and migrations are all reused. The line that shows operational experience is that one more stateful service usually becomes the bottleneck before vector search performance does.
    4. Be honest about the ceiling: past roughly ten million vectors in one table, HNSW index builds eat memory and write amplification shows; ANN plus metadata filtering is weaker than a purpose-built engine; horizontal scaling is whatever Postgres gives you. Refusing to name downsides reads as salesmanship.
    5. Commit to a rule: under a million vectors, needing joins or shared transactions, small team — pgvector. Tens of millions, retrieval as the primary workload, someone owning the service — dedicated store. Do not start with the dedicated store on day one.
    6. Expect the follow-up on migration cost. Switching stores does not require re-embedding — vectors belong to the model, not the store, so export and import; the cost is dual-write and rollout. Switching the embedding model is what forces a full recompute, and that is the real lock-in.

    答题要点

    • 三个判据:数据量级、要不要和业务表同事务提交、元数据过滤复不复杂
    • pgvector 的优势是同库同事务、普通 SQL 过滤、运维零新增——少一个有状态服务往往比性能更值钱
    • pgvector 的天花板:千万级向量时索引构建吃内存、写入放大、ANN 与过滤融合弱、扩展受限于 Postgres
    • 专用向量库给的是分布式分片、更强的过滤与 ANN 融合、混合检索,代价是多一个要备份要监控的有状态服务
    • 换向量库不用重算 embedding;换 embedding 模型才要全量重算,真正的锁定点是模型不是库

    Key points

    • Three criteria: scale, need for same-transaction commits with business tables, and filtering complexity
    • pgvector gives one database, one transaction, ordinary SQL filters and zero new operations — often worth more than raw performance
    • Its ceiling: memory-hungry index builds and write amplification at tens of millions, weaker ANN-plus-filter fusion, scaling limited to Postgres
    • Dedicated stores buy sharding, better filtered ANN and hybrid search, at the price of another stateful service to back up and monitor
    • Changing stores needs no re-embedding; changing the embedding model does — the lock-in is the model, not the database

D15 多 Agent 模式全景(Router/Supervisor、Planner-Executor、Critic、Swarm、Blackboard)与何时不该用;LangGraph 入门

  • 从单 Agent 升级到多 Agent,通常是被什么信号触发的?升级之后系统会多付出什么?What signals typically trigger the move from a single agent to a multi-agent system, and what does the upgrade cost you?
    国内高频海外高频进阶#multi-agent#cost#architecture

    分析过程 · 先想清楚再作答

    1. 这题考的是「你是被业务逼着拆的,还是照着博客拆的」。答「业务变复杂了」等于没答,面试官要的是**可观测的信号**:什么现象出现时你才动手。
    2. 给五个按出现顺序排的信号:一是提示词开始互相打架(加一条规则,另一个指标就掉);二是工具列表长到自己都要查文档;三是某一步的失败需要单独处理,不该整轮重来;四是想给某一步单独换模型;五是评估颗粒度不够,只能整体打分好或不好。
    3. 第四个信号要展开讲,它是唯一一个反常识的:多 Agent 通常更贵,但按步换模型是它唯一能省钱的场景——分诊这种短判断走便宜的小模型,拟方案走大模型。单 Agent 做不到按步换模型。这一条在面试里是明显的亮点。
    4. 然后主动给代价,不给代价的回答会被当成布道:延迟按步数乘倍数(原来两秒变六秒,而用户耐心大约三秒);成本按调用次数线性涨,因为每一步都要把当前状态重新塞进上下文,典型是三倍;调试难度按状态维度涨,出错要同时回答路由对不对、每个子 Agent 拿到的状态对不对、合并有没有互相覆盖。
    5. 再补一句反向判断,证明你不是无脑拆:工具太多的第一反应应该是合并工具、收敛描述,拆 Agent 是第二反应;质量差的第一反应应该是把单 Agent 版本调到最好,那个版本还会成为多 Agent 的对照基线。
    6. 可以预期的追问:拆完怎么证明比原来好?答:留住单 Agent 版本当基线,用同一批标准样本集跑 A/B,比准确率也比每次对话的成本与延迟。说不出对照基线的人,通常也说不清自己为什么拆。

    How to reason about it · think before answering

    1. This question tests whether business pain forced the split or a blog post did. Answering the business got complex is a non-answer; the interviewer wants observable signals — what symptom made you act.
    2. Give five, in the order they usually appear: prompts start fighting each other (add one rule, another metric drops); the tool list grows until you need the docs yourself; one step's failure needs isolated handling instead of redoing the whole turn; you want a different model for one specific step; and evaluation granularity is too coarse to say more than good or bad.
    3. Expand on the fourth, the counter-intuitive one: multi-agent is usually more expensive, but per-step model selection is the one case where it saves money — a short triage decision on a cheap small model, a drafting step on a larger one. A single agent cannot swap models per step. This lands well in interviews.
    4. Then volunteer the costs, or the answer reads as evangelism: latency multiplies by step count (two seconds becomes six, while user patience is about three); cost grows linearly with calls because every step re-sends the current state as context, typically three times; and debugging cost grows with state dimensions, since a failure now requires checking routing, each sub-agent's input state, and whether merges overwrote each other.
    5. Add the reverse check to show you are not splitting reflexively: too many tools should first prompt consolidation and tighter descriptions, with splitting as the second response; poor quality should first prompt tuning the single-agent version to its best, which then becomes the baseline the multi-agent version is measured against.
    6. Expect: how do you prove the split helped? Keep the single-agent version as a baseline and A/B both against the same golden set, comparing accuracy alongside per-conversation cost and latency. People who cannot name a baseline usually cannot explain why they split either.

    答题要点

    • 五个可观测信号:提示词互相打架、工具多到要查文档、某一步需要独立重试、想按步换模型、评估颗粒度不够
    • 按步换模型是多 Agent 唯一能省钱的场景:短判断走小模型、拟方案走大模型,单 Agent 做不到
    • 代价一:延迟按步数乘倍数,两秒变六秒,而用户对客服机器人的耐心大约三秒
    • 代价二:成本线性涨,每一步都要把状态重新塞进上下文,典型是原来的三倍
    • 代价三:调试难度按状态维度涨,所以多 Agent 和链路追踪必须一起上
    • 反向判断:工具多先合并再拆分,质量差先把单 Agent 调到最好——那个版本还是多 Agent 的对照基线

    Key points

    • Five observable signals: prompts fighting each other, a tool list you must look up, one step needing isolated retries, wanting a different model per step, and evaluation too coarse to act on
    • Per-step model selection is the only case where multi-agent saves money: small model for triage, larger model for drafting — impossible in a single agent
    • Cost one: latency multiplies with step count, two seconds becomes six, while patience for a support bot is about three
    • Cost two: spend grows linearly with calls since every step re-sends state as context, typically three times the original
    • Cost three: debugging cost grows with state dimensions, so multi-agent and tracing have to ship together
    • Reverse check: consolidate tools before splitting, and tune the single agent to its best first — that version becomes your baseline

D21 评估与可观测:golden set、LLM-as-judge、tracing、失败率/成本面板;Pi vs LangGraph 总结;W3 复盘

  • 什么时候该用 LangGraph 这类编排框架,什么时候不该用?When should you reach for an orchestration framework like LangGraph, and when should you not?
    国内高频海外高频进阶#architecture#framework-selection#langgraph

    分析过程 · 先想清楚再作答

    1. 这题最怕答成特性对比表。面试官想听的是判据,而且是能反过来说「不该用」的判据——只会说该用的人,通常是没被框架坑过的人。
    2. 先给三条该拆的判据(一条都不命中就别拆,也别引框架):**提示词里出现了互斥的行为要求**(既要严谨又要俏皮,调好一个另一个就坏);**工具多到选错率明显上升**;**某一步需要独立的失败与重试语义**(比如查库存失败该重试,拟退款方案失败该转人工,两者不能共用一套策略)。
    3. 然后给框架本身的判据,核心是一句:**要让多个角色并行写同一份状态,就必须显式;不需要并行,显式就是纯负担。** LangGraph 的价值是把合并规则声明在字段上——三个执行者并行写同一个工作区,谁的写入怎么合并,这件事必须有地方声明。反过来,一两个工具、循环最多两轮的场景,一个 while 加一个 switch 就够了,引入框架是净亏。
    4. 对比 Pi 这类高层 SDK 时,用维度而不是特性:上手成本(Pi 默认值多所以快,代价是模型和人设都是它替你挑的)、状态管理的显式程度(Pi 的历史在会话内部你感知不到,所以想改「同一个工作区怎么合并」时根本没有位置可改)、调试形态(Pi 给事件流是一条时间线,LangGraph 给逐节点增量和检查点是一棵可回放可分叉的树——**线性问题看时间线更快,多角色问题必须看树**)。
    5. 跨语言这条值得单独提,因为它常被忽略:**Java 和 Swift 都没有 LangGraph**,跨语言团队要么统一到 TS/Python,要么自己手写同一套结构。选框架的时候把这条算进去,比上线后再发现便宜。
    6. 可以预期的追问:那你怎么选?给一句可执行的:**你更怕看不见的默认值,还是更怕写不完的样板?** 怕前者选显式框架,怕后者选高层 SDK。这句话比任何特性表都实用。

    How to reason about it · think before answering

    1. The trap is answering with a feature matrix. The interviewer wants criteria, specifically criteria that can also say do not use it — people who can only argue for adoption usually have not been burned by a framework.
    2. Start with three criteria for splitting at all (if none holds, do not split and do not add a framework): the prompt contains mutually exclusive behavioural demands (rigorous and playful at once, where tuning one breaks the other); tools have grown numerous enough that selection error is visibly rising; or some step needs its own failure and retry semantics (an inventory lookup should retry, a refund draft should escalate to a human, and they cannot share one policy).
    3. Then the framework criterion, which is one sentence: if multiple roles write the same state concurrently, it must be explicit; if you do not need concurrency, explicitness is pure overhead. LangGraph's value is declaring merge rules on the field — with three executors writing one workspace, how those writes combine has to be declared somewhere. Conversely, with two tools and a loop that runs at most twice, a while and a switch suffice and a framework is a net loss.
    4. When comparing against a higher-level SDK like Pi, use dimensions rather than features: onboarding cost (Pi's defaults make it fast, at the price of it choosing your model and persona); explicitness of state (Pi keeps history inside the session, so when you want to change how one workspace merges there is no place to change it); and debugging shape (Pi gives an event stream, one timeline; LangGraph gives per-node deltas and checkpoints, a replayable and forkable tree — linear problems read faster as a timeline, multi-role problems require the tree).
    5. Cross-language deserves its own mention because it is routinely forgotten: neither Java nor Swift has LangGraph, so a polyglot team either standardises on TS/Python or hand-writes the same structure. Pricing that in during selection is cheaper than discovering it after launch.
    6. Expect: so how do you choose? Give something actionable: do you fear invisible defaults more, or endless boilerplate more? Fear the former and pick the explicit framework; fear the latter and pick the high-level SDK. That sentence is more useful than any feature table.

    答题要点

    • 先答该不该拆:提示词有互斥的行为要求、工具多到选错率上升、某步需要独立的失败与重试语义——一条不命中就别拆也别引框架
    • 框架判据一句话:多个角色并行写同一份状态就必须显式;不需要并行,显式就是纯负担
    • LangGraph 的价值是把合并规则声明在字段上;Pi 的历史在会话内部,想改合并方式根本没有位置可改
    • 调试形态不同:事件流是一条时间线,逐节点增量加检查点是一棵可回放可分叉的树;线性问题看时间线,多角色问题必须看树
    • Java 和 Swift 都没有 LangGraph,跨语言团队要么统一栈要么手写同一套结构,选型时就要算进去
    • 一句可执行的选型判据:更怕看不见的默认值就选显式框架,更怕写不完的样板就选高层 SDK

    Key points

    • First decide whether to split at all: mutually exclusive prompt demands, rising tool-selection error, or a step needing its own retry semantics — none holding means no split and no framework
    • The framework criterion in one line: concurrent writes to shared state require explicitness; without concurrency, explicitness is pure overhead
    • LangGraph's value is declaring merge rules on the field; Pi keeps history inside the session, leaving nowhere to change merge behaviour
    • Different debugging shapes: an event stream is a timeline, per-node deltas plus checkpoints are a replayable forkable tree — timelines for linear problems, trees for multi-role ones
    • Neither Java nor Swift has LangGraph, so polyglot teams standardise or hand-write the structure — price that in at selection time
    • An actionable heuristic: fear invisible defaults, choose the explicit framework; fear endless boilerplate, choose the high-level SDK

D23 MCP 与 Skills:协议、server/client、与 function calling 区别;Claude Agent SDK 一览

  • 什么场景下应该考虑用 MCP,而不是直接写 function calling?不该用的时候硬上会付出什么代价?When should you reach for MCP instead of plain function calling, and what does it cost when you shouldn't?
    国内高频海外高频进阶#mcp#architecture#trade-offs

    分析过程 · 先想清楚再作答

    1. 题眼在后半句。只会说「MCP 更标准更解耦」的人,等于说「微服务更解耦」——听起来对,但没有判据,面试官会立刻追问「那你们所有工具都做成 MCP server 了吗」。
    2. 先给判据,而且要是可执行的三条:能力要被多个宿主复用、能力由另一个团队或第三方维护、需要不改宿主代码就能增删能力。命中任意一条才考虑,**一条都不命中就直接写本地函数**——把默认答案摆成「不上」,这条比三条判据本身更能体现工程判断。
    3. 每条判据配一句为什么:多宿主复用把 N 乘 M 变成 N 加 M;别人维护时进程边界就是责任边界,他们改他们的、你不用发版;热插拔让加一个内部工具从一次发布降级成一次配置变更。
    4. 然后老实说代价,这是区分「用过」和「读过」的地方:多一个进程要保活、多一次握手要处理超时与重连、排障链路从一段变三段——工具没被调用,现在可能是模型没选、可能是 schema 翻译时丢了字段、也可能是 server 压根没起来。stdio 的子进程还要你自己回收,否则留孤儿进程。
    5. 还有一条容易被忽略但很加分:MCP 不改变你的成本结构。工具描述照样每轮都进上下文,工具多了照样会让模型选错——D5 那条「工具超过一定数量就该合并描述」在接了 MCP 之后一字不变,甚至更需要,因为现在别人可以往你的工具列表里塞东西。
    6. 可以预期的追问:那内部工具一律不上 MCP 吗?不是。有一类值得例外——你希望它能被 IDE 里的助手和运维机器人一起用,那第一条判据就命中了,即使它是你自己维护的。

    How to reason about it · think before answering

    1. The hinge is the second half. Answering only 'MCP is more standard and decoupled' is like saying 'microservices are more decoupled' — true-sounding but with no criterion, and the interviewer will immediately ask whether you turned every tool into an MCP server.
    2. Give three actionable criteria: the capability must be reused by more than one host, owned by another team or a third party, or added and removed without changing host code. Any one of them justifies MCP; none of them means write a local function. Making 'no' the default answer shows more engineering judgment than the criteria themselves.
    3. Attach a reason to each: multi-host reuse turns N times M into N plus M; external ownership makes the process boundary the responsibility boundary, so their change is not your release; hot-swapping demotes adding an internal tool from a deployment to a config change.
    4. Then state the costs honestly, which is where shipped experience shows: another process to keep alive, another handshake with its own timeouts and reconnects, and a debugging path that went from one hop to three — a tool that never got called might mean the model did not pick it, the schema lost fields in translation, or the server never started. On stdio you also own reaping the child process.
    5. One more point that is easy to miss and scores well: MCP does not change your cost structure. Tool descriptions still enter the context every turn, and more tools still degrade tool selection. The rule that you should consolidate tools past a certain count survives MCP unchanged — arguably it matters more, because now other people can add entries to your tool list.
    6. Expect the follow-up: so internal tools never go through MCP? Not quite. If you want the same capability available to an IDE assistant and an ops bot as well, the first criterion is met even though you own the code.

    答题要点

    • 三条判据,命中任意一条才考虑 MCP:多宿主复用、由他人维护、需要不改代码增删能力
    • 默认答案是不上:三条都不命中就直接写本地函数,这是更好的工程决策
    • 代价是多一个进程要保活、多一次握手要处理超时、排障从一段链路变成三段
    • MCP 不改变成本结构:工具描述照样每轮进上下文,工具过多照样会让模型选错,该合并还是要合并
    • 第三方能力接进来之后,工具列表不再完全由你掌控,这本身就是需要设计的一件事

    Key points

    • Three criteria, any one justifies MCP: reuse across hosts, ownership by another team, or add/remove without touching host code
    • The default is no — if none of the three apply, a local function is the better engineering decision
    • Costs: another process to supervise, another handshake with timeouts, and a debug path that grows from one hop to three
    • MCP does not change your cost structure: descriptions still enter context every turn and too many tools still hurt selection
    • Once third-party capabilities are attached, your tool list is no longer fully under your control, which is itself a design problem