Skip to content
All writing

Edge-to-cloud quality inspection on AWS: our architecture

How Easarc Vision gets a frame off an ordinary IP camera in a dusty weaving shed and turns it into a defect on a work order, in under two seconds, without losing anything when the link drops.

Engineering · 6 Aug 2026 · 14 min read

Easarc Vision has to work in a weaving shed where the air is full of lint, the lighting was installed in 2009, and the internet connection is a consumer broadband line that drops for twenty minutes most afternoons. Every architectural decision below follows from those three facts rather than from anything we would have chosen on a whiteboard.

This is a description of what we actually run, including the parts that are less elegant than we would like.

The constraints, stated honestly

  • The cameras are already there. Requiring industrial machine-vision cameras would double the cost of the deployment and kill it. We take whatever ONVIF/RTSP camera is mounted, which means variable resolution, variable frame rate and no hardware trigger.
  • The network is unreliable. Not slow — unreliable. Long stretches of fine, punctuated by total loss. Anything that assumes continuous connectivity fails in week one.
  • Latency has a hard ceiling. A defect flagged after the roll has been cut is worth almost nothing. We target under two seconds from frame capture to a supervisor’s phone.
  • Every customer’s defects are different. A process house and a garment unit share almost no taxonomy. A single global model is not useful to either.
  • Data cannot leave India. This is a customer requirement before it is a legal one, and it removes several otherwise attractive managed services.

The shape of it

Easarc platform architecture on AWSRequests flow from clients through Amazon Cognito to ECS Fargate and AWS Lambda, which publish to Amazon EventBridge and Amazon SQS, and read and write Aurora Serverless v2, Amazon S3, Amazon Bedrock and Amazon SageMaker. Amazon CloudWatch observes every layer. All services run in the ap-south-1 Mumbai region.ClientsWeb & mobile appFloor, office, buyer portalIP camerasRTSP capture on the lineWhatsApp Business APIBuyer status and supportIdentityAmazon CognitoUser pools, SSO, role-based accessComputeECS FargateFlow, Desk and Deploy control planeAWS LambdaInference callbacks, e-invoice jobsEventsAmazon EventBridgeStage changes, QC and dispatch eventsAmazon SQSRetry queues and buffered camera framesData and modelsAurora Serverless v2Orders, ledgersAmazon S3Clips, documentsAmazon BedrockDesk agentAmazon SageMakerVision modelsObservabilityAmazon CloudWatchMetrics, structured logs, alarms and audit trail
Every service above runs in ap-south-1 (Mumbai). Nothing leaves the region.
The same platform diagram we show on the homepage. Vision uses the Greengrass edge tier in front of it.

The edge tier

In each unit there is a small fanless x86 box on the LAN — the kind that costs about as much as a mid-range phone. It runs AWS IoT Greengrass, and it does four things.

Sampling, not streaming

We do not stream video to the cloud. At a typical printing line speed of 40 metres a minute, one frame every 2.25 seconds gives us a frame per 1.5 metres of cloth, which is finer than the defects we are looking for. That is roughly 1,600 frames per camera per hour instead of 100,000, and it is the single decision that makes the economics work at ₹4,999 per camera per month.

The sample interval is derived from the line speed, not fixed. When the machine slows, we sample less.

com.easarc.vision.sampler — recipe
# Component recipe for the edge sampler, deployed by AWS IoT Greengrass
ComponentName: com.easarc.vision.sampler
ComponentVersion: 1.6.0
ComponentConfiguration:
  DefaultConfiguration:
    cameras:
      - id: CAM-03
        rtsp: rtsp://10.0.4.31:554/stream1
        machine: PR-04
        # Line speed is 40 m/min; one frame per 1.5 m of cloth.
        sample_interval_ms: 2250
        roi: { x: 0.08, y: 0.12, w: 0.84, h: 0.76 }
    buffer:
      path: /var/lib/easarc/spool
      max_bytes: 21474836480      # 20 GB — about 14 hours at this rate
      policy: drop_oldest
    upload:
      endpoint: ingest.easarctech.com
      batch_size: 8
      max_inflight: 2
      backoff: exponential

Buffering, because the link will drop

Frames are written to a local spool before any upload is attempted. The spool holds 20 GB, which at our sample rate is around fourteen hours of production. When the link returns, the backlog drains at a rate limited so it does not saturate the same connection the office is using.

The policy when the spool fills is drop_oldest, and we argued about this. Dropping the newest keeps a continuous record of the earliest failure; dropping the oldest keeps the record closest to now. We chose oldest because a supervisor acting on the last hour is worth more than a complete archive of a fault that has already run through 8,000 metres.

Cropping to a region of interest

The camera sees the machine, the floor and usually part of a wall. We crop to the cloth path at the edge, which cuts the payload by half or more and — more importantly — removes most of the incidental footage of people working, which matters both for the DPDP Act and for how the operators feel about the camera.

Store-and-forward, not request-response

The edge box never waits for a reply. It uploads batches of eight frames to an ingestion endpoint, marks them acknowledged, and moves on. Everything downstream is asynchronous, which is what lets a twenty-minute outage be a twenty-minute delay rather than a twenty-minute hole.

The cloud tier

  1. Ingestion. An ECS Fargate service behind an ALB accepts the batch, writes frames to S3, and puts one message per frame on SQS. It does nothing else. The one job of this tier is to never be the reason a frame is lost.
  2. Inference. Lambda consumers pull from SQS and call a SageMaker endpoint running that customer’s model. Batching happens at the endpoint rather than in Lambda, so we get GPU efficiency without holding frames in a function.
  3. Event fan-out. A detection above the customer’s confidence threshold is published to EventBridge as a single well-typed event. Everything that reacts — the supervisor alert, the write to the Flow work order, the running defect-rate calculation — is an independent rule on that bus.
  4. Persistence. Defect events go to Aurora Serverless v2 alongside the order data, which is what makes “defect rate by shift for this buyer’s orders” a single query rather than a join across two systems.

The event on the bus looks like this.

vision.defect.detected
{
  "event_id": "evt_01J9ZK4M7Q2X8V",
  "camera_id": "CAM-03",
  "machine_id": "PR-04",
  "shift": "B",
  "operator_id": "OP-2291",
  "work_order": "ESR-2026-0431",
  "captured_at": "2026-08-08T14:21:06.412+05:30",
  "received_at": "2026-08-08T14:21:07.884+05:30",
  "defects": [
    {
      "class": "weft_bar",
      "confidence": 0.91,
      "bbox": [0.24, 0.38, 0.38, 0.47],
      "severity": "major"
    },
    {
      "class": "oil_stain",
      "confidence": 0.77,
      "bbox": [0.62, 0.61, 0.71, 0.73],
      "severity": "minor"
    }
  ],
  "frame_uri": "s3://easarc-vision-ap-south-1/clips/2026/08/08/CAM-03/1421064.jpg",
  "model_version": "rajhans-v7"
}

The fields that matter most are the boring ones. work_order, machine_id, shift and operator_id are what turn a detection into something someone can act on, and all four are resolved at the edge from the machine the camera is bound to and the schedule in Flow — not inferred later.

Where the two seconds goes

Latency budget from capture to alert
StageTypicalp95
Capture, crop and encode at the edge90 ms160 ms
Upload to ingestion (batched)310 ms840 ms
S3 write and SQS enqueue40 ms110 ms
SQS to Lambda pickup120 ms390 ms
SageMaker inference280 ms460 ms
EventBridge fan-out and alert delivery210 ms520 ms
End to end1.05 s2.48 s

The upload leg dominates and is the least predictable, because it is the only part running on somebody else’s broadband. This is why the alert path is optimistic: we deliver on the first detection above threshold rather than waiting to aggregate.

Models, and the part nobody enjoys

Every customer gets their own model, fine-tuned from a shared backbone on their own labelled examples. The first two weeks of any Vision deployment are spent collecting those examples, and this is the genuinely hard part of the product.

A new unit does not have a labelled dataset. What it has is a QC person who can point at a defect and name it. So the first fortnight runs in shadow mode: we sample, we run the base model, and we show the QC person a queue of candidate frames to confirm or reject on a tablet. Around 400 to 900 confirmed examples per defect class is where precision becomes useful.

Four things we got wrong first

  1. We streamed video initially. It worked beautifully in our office and fell over on the first real broadband line. Sampling was not a compromise; it was the correct design and we came to it late.
  2. We ran inference at the edge. It seemed obvious — lower latency, less bandwidth. In practice, updating a model across thirty dusty boxes in thirty different units is a fleet-management problem we had no business taking on at our size. Cloud inference costs us 300 ms and saves us an operations team.
  3. We alerted on every detection. Supervisors muted it within two days, which is worse than no alerting at all because it looks like it is working. Alerts are now rate-limited and threshold-based, and the default threshold is deliberately conservative.
  4. We showed the model’s confidence to the floor. “0.77 oil stain” means nothing to a supervisor and quietly undermines trust in the ones that are right. The floor now sees a defect and a severity; the confidence score lives in the analytics view where it belongs.

Data residency, concretely

Every component described here runs in ap-south-1. Frames land in an S3 bucket in Mumbai, inference runs on a SageMaker endpoint in Mumbai, and the Aurora cluster is in Mumbai with backups in the same region. Clip retention follows the plan — 30 days on Starter, 90 on Growth — and deletion is a lifecycle policy on the bucket rather than a job somebody has to remember to run.

The one thing that leaves the region is aggregate telemetry with no customer content in it: latency histograms, error counts, model version distribution. That is listed in our data processing addendum along with every sub-processor.

If you want to see the output rather than the plumbing, Easarc Vision has the inspection view, and the live demo has the quality dashboard with real-shaped data in it.

Get started

This is the problem we build for

Easarc Flow, Vision, Deploy and Desk exist because of the things described above. Put one of them in front of a single product line and judge it on what changes.

14-day free trial, no card required. GST extra at 18%.