Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
155382 stories
·
33 followers

Donut Lab's 'Solid-State' Battery Exposed As Regular Li-Ion

1 Share
A battery researcher's investigation, backed by more than 20 independent experts, claims Donut Lab's much-hyped "solid-state" battery is actually a conventional lithium-ion cell, with voltage curves and expansion data matching high-nickel NCM chemistry rather than the promised sodium-ion solid-state design. Electrek reports the company raised about $25 million from more than 1,300 mostly small investors on claims of 400 Wh/kg energy density, 100,000-cycle life, and 5-minute charging that now appear unsupported. From the report: The investigation consulted over 20 independent battery experts, including Julian Zanau from the Fraunhofer Research Institute, Dr. Yahim San from Justus-Liebig University, Tom Bicha from Leona, and Dr. Yuo Hesca from Seinajoki University of Applied Sciences. Every single one confirmed the tested cell is lithium-ion. There are two key pieces of evidence. First, the voltage curves from VTT testing match high-nickel lithium-ion cells (NCM chemistry). The cell sits at 3.7-3.8 volts at 50% state of charge -- right where lithium-ion cells operate. Sodium-ion cells don't go significantly past 3.5 volts at 50% SOC. The second piece of evidence is even more damning: VTT's cell expansion data. When a battery charges, ions squeeze into the anode material, causing it to expand in a predictable pattern. A graphite anode produces a distinctive "kink" in the expansion curve around 50-70% state of charge, caused by how ions reorder themselves in graphite's layered structure. The Donut Lab cell shows exactly that kink. This is critical because sodium ions are physically too large to fit into graphite layers. The graphite anode signature proves the cell uses lithium ions. The investigation puts it well: "it's like we have a slightly noisy fingerprint and a picture of the suspect's face. And yet again, it's a match." The calculated energy density? About 298 Wh/kg -- what you'd expect from a good lithium-ion cell, not the 400 Wh/kg claimed. The investigation reveals that the battery technology traces back to CT Coatings, a German company with an "eclectic" array of patents -- including inventions for screen-printed paving slabs, menu folders, and warning triangles. CT Coatings promised Nordic Nano and Donut Lab a screen-printed sodium-ion solid-state battery. What it delivered was a lithium-ion pouch cell.

Read more of this story at Slashdot.

Read the whole story
alvinashcraft
59 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Meet ArchAstro: Ex-Stripe, Microsoft and Meta vets assemble powerhouse team for cross-company AI agents

1 Share
Vivek Sharma, Rob Masson, Tore Hanssen and Calvin Grunewald of ArchAstro (ArchAstro photo)

ArchAstro just emerged from stealth with an artificial intelligence network designed to automate complex, cross-company software deployments and integrations.

Founded earlier this year by a team of veteran engineers from Microsoft, Stripe, Statsig and Meta, the Seattle-area startup is tackling a complex problem — the prolonged period it often takes for corporate clients to integrate newly purchased software into custom enterprise environments.

ArchAstro is led by co-founder and CEO Vivek Sharma, a former Microsoft distinguished engineer who most recently worked in technical leadership roles at Meta and Stripe. 

GeekWire first got wind of the new startup back in January, when we noted Sharma’s departure from Stripe. At the time, he simply offered a cryptic message that they were using “AI’s potential to fundamentally change how people work.”

Now, more details are coming to light, including pre-seed funding of $6.2 million from a marquee list of investors. 

In a blog post announcing the new company, Sharma said “even the simplest B2B software requires hand-to-hand combat to properly integrate.”

Hand-to-hand combat may be an apt description of the challenging business problem that ArchAstro is looking to tackle, an endeavor that Sharma admits is “a very difficult problem.” 

Traditional artificial intelligence agents tend to operate entirely within a single organization’s firewall, while ArchAstro’s agents are designed to work across distinct corporate boundaries. 

Securely connecting these disparate systems is no easy task. That’s why the company says its “privacy-aware” AI agents — what it calls Forward Deployed Agents— are designed to handle cross-company integrations, migrations and bug fixes quickly and securely. 

“The key thing we’re enabling is a continuous connection enforced with code, built off the most current context across both companies,” Sharma tells GeekWire. 

Of course, there is always the concern of possible data leakage between two entities — a potential showstopper for any corporate chief information security officer. But Sharma said they are addressing that concern. 

Since customers control their own agents and how they operate, they choose how they interact. 

“Instead of moving data between companies and managing leak risk, you’re just adhering to shared ‘acceptance tests’ that ArchAstro hosted agents create and maintain across both,” Sharma said. “Code is also easy to evaluate and check for correctness. This is how engineering systems have always worked, and we’re extending that discipline between companies rather than within one.” 

Sharma said the ArchAstro system also could be used to help answer cross-company questions, like a custom agent assisting account managers with their customers. 

“Either way, we work with the customer to share only what’s appropriate, and our runtime enforces that with additional safeguards layered on as needed,” he said. 

In that regard, ArchAstro acts as a secure, automated translation layer, allowing two entirely different corporate systems to speak the same language and verify each other’s work instantly based on a shared set of rules. That seamless, secure flow of collaboration between companies translates directly to dollars saved.

“Product teams ship fast, but customers take months, sometimes years, to deploy what they buy,” Sharma noted. He added that delayed deployments result in revenue loss, customer churn and engineering burnout spent debugging individual setups rather than building what is next.

The system is designed to plug directly into existing developer workflows, including Cursor, Claude and Codex.

Given the complexities involved, Sharma’s founding engineering team includes veterans who previously worked on some thorny technical challenges: Microsoft Exchange Server and Office 365, Stripe Billing and Connect, and engineering platforms at Meta, Atlassian and Statsig.

The team includes

  • Tore Hanssen, who was a founding engineer at Statsig, the Bellevue, Wash.-based startup acquired last September by OpenAI. He previously worked at Meta.
  • Robert Masson, a senior staff data scientist in Meta’s Seattle office, who spent nearly 11 years with the company before going to Atlassian early last year.
  • Calvin Grunewald, who spent nine years as a Facebook director of engineering, based in Seattle. He was most recently at Stripe.
  • Rafael Brandao Lobo, a founding engineer who previously spent more than a decade building brand advertising and gaming products at Facebook/Meta. 
  • Bruno Garcia, an open source startup founder who previously worked at PlayCo and Sega.

Rakesh Parida, Head of Forward Deployed Engineering at Stripe, said utilizing AI agents to create strong technical connections between companies is a major strategic advantage. 

“ArchAstro is making that model repeatable at scale, enabling continuous integrations, deployments, and migrations across companies, with the security, (forward deployed engineering) oversight, and judgment that serious software partnerships require,” Parida said. “The future of software partnerships isn’t just about going live together. It’s about staying live together.”

Two Fortune 500 companies have already begun utilizing the platform as design partners, though Sharma declined to say who they are. There’s also the potential threat of Microsoft, Google, Amazon or others entering the market, given their interests in making sure B2B customers are satisfied in deploying agentic AI systems.

Sharma said they are fully expecting competition in the nascent sector, and in some cases they are already speaking to the big players.

“But their demand is so high that they don’t have the time or the focused energy to build a solution like ours,” he said. “We think we can accelerate their revenue and help these larger companies scale even further.”

ArchAstro is backed by venture capital firms 20VC — the London-based firm led by Harry Stebbings — and Kyber Knight — whose investments include Cruise, SpaceX and Anduril. Its angel investors include a who’s who of technology leaders:

Based in Seattle, the company employs seven people. Sharma said they are deliberately “staying lean,” adding that a smaller team forces them to be “extremely nimble and invent a path to value.”

He’s also excited to build the startup in Seattle, which he says has “some of the best engineers anywhere.”

“If you want to be a serious B2B company, at some point you have to venture up to Seattle,” he said.

Read the whole story
alvinashcraft
1 hour ago
reply
Pennsylvania, USA
Share this story
Delete

Expeditors cuts 230 tech jobs in Seattle region, ending decades-long policy against layoffs

1 Share
Expeditors had previously been expanding its technology staff, according to its financial reports. (Alamy Photo / JHVEPhoto)

Expeditors International, the Seattle-area logistics company known for never laying off employees, cut about 230 technology-related jobs in the region on Monday, ending a tradition that had been a point of pride for much of the company’s history.

The layoffs hit software developers, quality-assurance testers, project managers, business analysts and others across Expeditors’ offices in downtown Seattle, Bellevue, Lynnwood and Federal Way, according to laid-off employees and others with knowledge of the situation.

Company officials did not respond to messages from GeekWire seeking comment Monday afternoon and evening. The reasons for the layoffs were not clear.

The cuts in the Seattle area represent about 15% of the company’s global tech workforce. Posts on Reddit and LinkedIn indicate that there may have been some additional job cuts outside the region. Expeditors employed about 1,500 people in information systems worldwide as of March 31, up from about 1,360 a year before, according to its first-quarter financial report.

Expeditors was founded in Seattle in 1979 as a single-office ocean freight forwarder and went public on the Nasdaq in 1984. Its stock now trades on the New York Stock Exchange. The company has about 20,000 employees worldwide and posted $11.07 billion in revenue in 2025, with profits of $810 million.

Under Peter J. Rose, a co-founder who served as CEO from 1988 to 2013, it built a reputation for not laying off employees. It held to that practice through the 2008-09 financial crisis and the COVID-19 pandemic, and even as a wave of layoffs swept the technology industry in 2022 and 2023.

The cuts follow major leadership changes. Daniel Wall, who started in 1987 as a messenger and worked his way up over nearly four decades, became CEO in April 2025, succeeding Jeffrey Musser. The tech organization is run by Courtney Hawkins, senior vice president and CIO, who joined Expeditors in 2024, after roles at Starbucks, Nike, Nordstrom and Zulily.

One former employee said there had been hints about the possible cuts for several months, including discussion of a restructuring plan and new job titles in the technology organization.

Another clue, in retrospect, was a change to the company’s website: As recently as January of this year, Expeditors’ online corporate history page credited “our no layoff policy” for making 2010 the company’s best year ever, according to a version of the page captured by the Internet Archive.

By last month, the page had been changed to call it “our short-term no layoff policy.”

Read the whole story
alvinashcraft
1 hour ago
reply
Pennsylvania, USA
Share this story
Delete

Creating checkpoints by gaslighting a Postgres database​​​​‌‍​‍​‍‌‍‌​‍‌‍‍‌‌‍‌‌‍‍‌‌‍‍​‍​‍​‍‍​‍​‍‌​‌‍​‌‌‍‍‌‍‍‌‌‌​‌‍‌​‍‍‌‍‍‌‌‍​‍​‍​‍​​‍​‍‌‍‍​‌​‍‌‍‌‌‌‍‌‍​‍​‍​‍‍​‍​‍‌‍‍​‌‌​‌‌​‌​​‌​​‍‍​‍​‍‌‍​‌‍‌‌​​‍‍‌​‌‌​‌‍​‌‌‍​‌‍‍‌‍‌‌‍‌‍‌‌‌​‍‌‍‌‍‌‍​‌‍‌‌​‍‍‌‍​‌‍​‍‌‍‍‌‌‍‍‌‌​‌‍‌‌‌‍‍‌‌​​‍‌‍‌‌‌‍‌​‌‍‍‌‌‌​​‍‌‍‌‌‍‌‍‌​‌‍‌‌​‌‌​​‌​‍‌‍‌‌‌​‌‍‌‌‌‍‍‌‌​‌‍​‌‌‌​‌‍‍‌‌‍‌‍‍​‍‌‍‍‌‌‍‌​​‌​‍‌‌‍​‌‍​‍​​​‌‍​‌‍​‍​​​‍‌​‍‌‌‍‌‍‌‍​‌‍​​‍‌​‍‌​‌​‌‍​‍​​​​‍‌​‍‌​‍‌​​‍‌‍‌‌​‌‍​‍‌​‌‍‌‍​‌​‍​‌‍​‌‌‍‌​‌‍‌‌‌‍‌‍​‍​‌‍‌​‌‍​​​​​​‍​‍‌‌​‌‍‌‌​​‌‍‌‌​‌‌‍​‍‌‍​‌‍‌‍‌‌‌​​‌‍‌​‌‌​​‍‌​​‌‍​‌‌‌​‌‍‍​​‌‌‌​‌‍‍‌‌‌​‌‍​‌‍‌‌​‌‍​‍‌‍​‌‌​‌‍‌‌‌‌‌‌‌​‍‌‍​​‌‌‍‍​‌‌​‌‌​‌​​‌​​‍‌‌​​‌​​‌​‍‌‌​​‍‌​‌‍​‍‌‌​​‍‌​‌‍‌‍​‌‍‌‌​​‍‍‌​‌‌​‌‍​‌‌‍​‌‍‍‌‍‌‌‍‌‍‌‌‌​‍‌‍‌‍‌‍​‌‍‌‌​‍‍‌‍​‌‍​‍‌‍‌‍‍‌‌‍‌​​‌​‍‌‌‍​‌‍​‍​​​‌‍​‌‍​‍​​​‍‌​‍‌‌‍‌‍‌‍​‌‍​​‍‌​‍‌​‌​‌‍​‍​​​​‍‌​‍‌​‍‌​​‍‌‍‌‌​‌‍​‍‌​‌‍‌‍​‌​‍​‌‍​‌‌‍‌​‌‍‌‌‌‍‌‍​‍​‌‍‌​‌‍​​​​​​‍​‍‌‍‌‌​‌‍‌‌​​‌‍‌‌​

1 Share
Ryan welcomes Bryan Clark, director of product for Lakebase at Databricks, to discuss what happens when AI agents become the primary creators and users of databases; why agents are “sloppy” about cleaning up infrastructure; and how database branching, scale-to-zero, and centralized access control can help teams keep up with agent-driven development.​​​​‌‍​‍​‍‌‍‌​‍‌‍‍‌‌‍‌‌‍‍‌‌‍‍​‍​‍​‍‍​‍​‍‌​‌‍​‌‌‍‍‌‍‍‌‌‌​‌‍‌​‍‍‌‍‍‌‌‍​‍​‍​‍​​‍​‍‌‍‍​‌​‍‌‍‌‌‌‍‌‍​‍​‍​‍‍​‍​‍‌‍‍​‌‌​‌‌​‌​​‌​​‍‍​‍​‍‌‍​‌‍‌‌​​‍‍‌​‌‌​‌‍​‌‌‍​‌‍‍‌‍‌‌‍‌‍‌‌‌​‍‌‍‌‍‌‍​‌‍‌‌​‍‍‌‍​‌‍​‍‌‍‍‌‌‍‍‌‌​‌‍‌‌‌‍‍‌‌​​‍‌‍‌‌‌‍‌​‌‍‍‌‌‌​​‍‌‍‌‌‍‌‍‌​‌‍‌‌​‌‌​​‌​‍‌‍‌‌‌​‌‍‌‌‌‍‍‌‌​‌‍​‌‌‌​‌‍‍‌‌‍‌‍‍​‍‌‍‍‌‌‍‌​​‌​‍‌‌‍​‌‍​‍​​​‌‍​‌‍​‍​​​‍‌​‍‌‌‍‌‍‌‍​‌‍​​‍‌​‍‌​‌​‌‍​‍​​​​‍‌​‍‌​‍‌​​‍‌‍‌‌​‌‍​‍‌​‌‍‌‍​‌​‍​‌‍​‌‌‍‌​‌‍‌‌‌‍‌‍​‍​‌‍‌​‌‍​​​​​​‍​‍‌‌​‌‍‌‌​​‌‍‌‌​‌‌‍​‍‌‍​‌‍‌‍‌‌‌​​‌‍‌​‌‌​​‍‌​​‌‍​‌‌‌​‌‍‍​​‌‌‍‌‌‌‍​‌‍​‌‍‌‌‌​‍‌​​‌‌​​‌‍​‍‌‍​‌‌​‌‍‌‌‌‌‌‌‌​‍‌‍​​‌‌‍‍​‌‌​‌‌​‌​​‌​​‍‌‌​​‌​​‌​‍‌‌​​‍‌​‌‍​‍‌‌​​‍‌​‌‍‌‍​‌‍‌‌​​‍‍‌​‌‌​‌‍​‌‌‍​‌‍‍‌‍‌‌‍‌‍‌‌‌​‍‌‍‌‍‌‍​‌‍‌‌​‍‍‌‍​‌‍​‍‌‍‌‍‍‌‌‍‌​​‌​‍‌‌‍​‌‍​‍​​​‌‍​‌‍​‍​​​‍‌​‍‌‌‍‌‍‌‍​‌‍​​‍‌​‍‌​‌​‌‍​‍​​​​‍‌​‍‌​‍‌​​‍‌‍‌‌​‌‍​‍‌​‌‍‌‍​‌​‍​‌‍​‌‌‍‌​‌‍‌‌‌‍‌‍​‍​‌‍‌​‌‍​​​​​​‍​‍‌‍‌‌​‌‍‌‌​​‌‍‌‌​‌‌‍​‍‌‍​‌‍‌‍‌‌‌​​‌‍‌​‌‌​​‍‌‍‌​​‌‍​‌‌‌​‌‍‍​​‌‌‍‌‌‌‍​‌‍​‌‍‌‌‌​‍‌​​‌‌​​‍‌‍‌​​‌‍‌‌‌​‍‌​‌​​‌‍‌‌‌‍​‌‌​‌‍‍‌‌‌‍‌‍‌‌​‌‌​​‌‌‌‌‍​‍‌‍​‌‍‍‌‌​‌‍‍​‌‍‌‌‌‍‌​​‍​‍‌‌
Read the whole story
alvinashcraft
1 hour ago
reply
Pennsylvania, USA
Share this story
Delete

Make Your Copilot Credits Count: A Student's Guide to Smarter AI Usage

1 Share

If you're a student enrolled in GitHub Education, you already have something most developers pay for: free access to GitHub Copilot and its premium features. That's incredible. But here's the thing, free access doesn't mean unlimited usage, and not all AI interactions cost the same. Every chat message, every agent task, every model call consumes something called AI Credits, and knowing how they work will help you use Copilot smarter, produce better code, and build the kind of disciplined AI habits that professional developers are only just starting to learn.

This post is inspired by a fantastic deep-dive from my collegaue developer advocate Bruno: "GitHub Copilot and Tokens: How to Keep Using AI Without Burning Your Budget" . We've taken those professional lessons and tailored them specifically for students  because your learning environment, your assignments, and your goals are different from a seasoned engineer at a tech company.

TL;DR: Use autocomplete before chat. Choose the right model. Keep context small. Start fresh chats often. Plan before you build. These habits will make you a better developer and stretch your credits further.

What Are AI Credits and Why Do They Matter?

When you interact with GitHub Copilot through chat, agent mode, or inline edits the model processes tokens. Tokens are small chunks of text (roughly 3–4 characters each). Every interaction consumes:

  • Input tokens — everything sent to the model (your message, attached files, chat history, instructions)
  • Output tokens — everything the model generates back to you
  • Cached tokens — context the model reuses from previous turns (cheaper)

These tokens are converted to AI Credits, where 1 AI Credit = $0.01 USD. Different models have very different token costs a lightweight model like GPT-5 mini charges $0.25 per million input tokens, while a powerful model like GPT-5.5 charges $5.00 per million input tokens (20x more expensive). Using the wrong model for a simple task is like taking a taxi to a destination that's a 5-minute walk.

See the official pricing table: GitHub Copilot Models and Pricing .

Figure 1: The four cost tiers of Copilot interactions. Autocomplete and Next Edit Suggestions are free — they do not consume AI Credits on paid plans

Strategy 1: Tab Before Chat  The Free Tier is Powerful

Here is the single most impactful habit you can build: always try autocomplete before opening chat.

According to GitHub's official billing documentation, code completions and Next Edit Suggestions are not billed as AI Credits on paid plans. That means every time you press Tab to accept an inline suggestion, you are getting AI assistance for free.

Use autocomplete (Tab) for:

  • Completing a line or a simple function
  • Generating repetitive boilerplate (constructors, properties, getters/setters)
  • Completing a repeated pattern you've started
  • Writing obvious next lines like console.log, imports, or variable declarations
  • Adjusting variable names inline

Only move to Inline Edit (Ctrl+I / Cmd+I) when autocomplete isn't enough for a local change. Only open a Chat window when you need genuine reasoning an explanation, a plan, or a multi-step solution.

As Bruno puts it: "The most expensive model in the world should not be helping you write public string Name { get; set; }. That's what Tab is for. And coffee."

Strategy 2: Choose the Right Model for the Job

GitHub Copilot gives you access to models from OpenAI, Anthropic, and Google  each at different price points and capability levels. The key insight from VS Code's official Copilot usage guide is: reserve powerful reasoning models for tasks that genuinely need them.

Your TaskRecommended Model TierExample Models
Simple question or boilerplateLightweightGPT-5 mini, Gemini 3 Flash
Code explanation or basic docsLightweightGPT-5 mini, GPT-5.4 nano
Writing tests or debugging a single functionMedium / VersatileClaude Haiku 4.5, GPT-5.4
Multi-file refactor or code reviewMedium / VersatileClaude Sonnet 4.6, GPT-5.4
Complex system design or architecturePowerfulClaude Opus 4.7, GPT-5.5
Long agentic workflowsPowerful (scoped!)Claude Opus 4.8, GPT-5.5
Not sure what you needAuto (recommended default)Copilot selects for you

GitHub Copilot's Auto Model Selection feature automatically chooses a model based on task complexity, availability, and policies. For most students, Auto should be your default  only switch manually when you have a specific reason. And when the complex task is done, switch back to Auto or a lighter model.

Strategy 3: Context is Currency  Smaller is Smarter

Here's the counterintuitive truth that surprises most developers: the expensive part of a prompt is usually not the question you type  it's everything surrounding it.

Every token consumed by Copilot includes:

  • All your previous chat messages in the session
  • Every file you have open or attached
  • Workspace search results Copilot pulled in
  • Build output, terminal logs, or diff content
  • Responses from any MCP (Model Context Protocol) servers you have enabled
  • Your custom instructions file (.github/copilot-instructions.md)

A single question inside a conversation with 80 messages, 12 open files, and 3 tool call results can cost significantly more than the same question asked fresh in a new chat with one relevant file attached.

Figure 2: The same task asked two ways. Scope your prompts to save credits and often get better answers.

Practical rules for context management:

  • Attach only 2–3 relevant files — not your entire project
  • Don't ask Copilot to analyse the whole repo when you only need changes in one module
  • Paste only the first relevant error from a log, not 2,000 lines of output
  • Remove timestamps and duplicate stack traces from pasted logs
  • State the expected output format explicitly so the model stops early
  • Use /compact in VS Code Chat to summarise a long conversation without losing key context
  • Use /fork to explore an alternative direction without polluting the main conversation

Strategy 4: Start Fresh Chats When You Change Tasks

This is one of the simplest optimisations  and one of the most ignored. The VS Code Copilot usage guide is explicit about it: when a conversation grows, it carries context from all previous messages. If you switch to an unrelated task in the same session, the model still processes that irrelevant history and you pay for it in credits.

Bad pattern:

Chat session:
  - "Help me fix the JWT bug in auth.ts"   [10 messages]
  - "Now write unit tests for my sorting algorithm"  [still in same chat!]
  - "Can you generate the README for my project?"    [still in same chat!]
  - "Now debug this CSS layout issue..."             [still in same chat!]

Smart pattern:

Chat 1: "Fix JWT bug in auth.ts" - DONE, close chat.
Chat 2: "Write unit tests for sorting algorithm" - DONE, close chat.
Chat 3: "Generate README for project" - fresh context, fresh cost.

New task = new chat. Your human brain benefits too — focused sessions produce better outcomes than sprawling multi-topic conversations.

Strategy 5: Plan Before You Build  Use Agent Mode Wisely

Agent mode is one of the most powerful Copilot features for students working on larger assignments — it can create files, run terminal commands, edit across multiple files, and execute tests. But agent mode also carries the highest token cost, because it loops: it plans, acts, observes tool output, then plans again.

The VS Code documentation recommends separating planning from implementation to reduce rework and back-and-forth. Here's a phased approach that saves credits and produces better results:

Figure 3: The credit-smart workflow. Always try the cheaper option first, escalate only when needed.

Phase 1: Plan (lightweight model, low cost)

I need to add user authentication to my Express app.
Before writing any code, give me a step-by-step plan
covering which files to create, which packages to install,
and what tests to write. Do not write code yet.

Phase 2: Scoped Implementation (one feature at a time)

Using the plan we agreed, implement only Step 1:
create src/middleware/auth.ts with JWT validation.
Do not modify any other files yet.

Phase 3: Validate

Run the existing tests in tests/auth.test.ts
and report the results. Fix only test failures
related to the new auth middleware.

Phase 4: Cleanup

The implementation is complete.
Update README.md with setup instructions for the auth module.
Keep it under 200 words.

Each phase is small, scoped, and verifiable. You can stop at any phase, check the result, and only continue when you're satisfied. This dramatically reduces expensive re-runs where the agent reverses its own changes.


Strategy 6: Review Your MCP Servers and Custom Instructions

MCP Servers

MCP (Model Context Protocol) servers let Copilot connect to external tools  databases, GitHub issues, Jira, Slack, browser automation, and more. Each enabled server expands what the agent can do, but also adds to the context the model must consider, which increases token usage.

For students, a practical rule: only enable MCP servers relevant to your current project. If you're working on a simple Python web app, you probably don't need browser automation, a Kubernetes connector, and a Slack integration all active at the same time.

See the VS Code MCP servers documentation for how to enable, disable, and configure them.

Custom Instructions

A .github/copilot-instructions.md file in your repository lets you give Copilot standing instructions — coding standards, testing commands, architecture conventions. This is a fantastic feature. But that file is included in every prompt's context, so a bloated instructions file costs credits on every single interaction.

A good custom instructions file is:

  • Short — under 200 words for a student project
  • Specific to this repository's real conventions
  • Clear about test commands (e.g., npm test, pytest)
  • Free of generic advice that applies to every codebase on earth

Example of a good student instructions file:

# Copilot Instructions for MyWebApp

Language: TypeScript (strict mode)
Framework: Express.js with Prisma ORM
Tests: Run with `npm test` (Jest)
Lint: Run with `npm run lint` (ESLint + Prettier)

Conventions:
- Use async/await, not callbacks
- Validate all request inputs with Zod
- Keep controllers thin; put logic in service files
- Write a test for every new public function

That's it. Short, actionable, and genuinely useful — not a 500-line manifesto.


Strategy 7: Use Traditional Tools First

AI is excellent for reasoning, explaining, planning, and connecting ideas. It is not the right tool for every job. Before reaching for Copilot chat, ask yourself whether a traditional tool can answer your question faster, cheaper, and more reliably:

  • Compiler / type-checker — to find type errors (TypeScript, mypy)
  • Linter — to find style and logic issues (ESLint, Pylint, Checkstyle)
  • Formatter — to fix formatting (Prettier, Black, gofmt)
  • Test runner — to confirm whether your code works (Jest, pytest, JUnit)
  • Debugger — to step through execution and inspect state
  • Docs / Stack Overflow — for well-documented APIs and common patterns

If your linter tells you there's a missing import, fix it directly — don't ask Copilot to analyse your code to find it. Let deterministic tools do deterministic work, and let AI do the reasoning where it genuinely adds value.


Your GitHub Education Benefits: What You Get

If you haven't already, apply for GitHub Education with your school email address. Once verified, you receive:

  • Free GitHub Copilot including premium features — see how to enable Copilot as a student
  • Free GitHub Codespaces — 180 core hours per month, equivalent to GitHub Pro (great for browser-based coding with Copilot built in)
  • GitHub Student Developer Pack — free access to dozens of professional tools from GitHub's partners, including cloud credits, domains, and IDEs
  • GitHub Classroom — your instructors can manage assignments and provide feedback
  • GitHub Community Exchange — discover and contribute to student-built projects
  • Campus Experts program — become a student leader in your tech community

These benefits are designed to give you real-world tools in an educational setting. Copilot is the standout feature — it's the same tool professional developers use every day. Using it wisely during your studies means you'll arrive in the workforce already ahead of the curve.


Pre-Prompt Checklist for Students

Before you fire off your next Copilot prompt, run through this checklist. It takes 10 seconds and can save significant credits — and more importantly, it builds the mental habits of a professional AI user.

Figure 4: Two-column checklist covering what to check before opening chat and when writing your prompt.

Before you open chat:

  • ☐ Can Tab / autocomplete solve this?
  • ☐ Is inline edit (Ctrl+I) enough for this local change?
  • ☐ Can a linter, compiler, or test runner answer this?
  • ☐ Is this a different task from my last message? If so, start a new chat.
  • ☐ Am I on Auto model selection (or the right tier for this task)?
  • ☐ Should I ask for a plan before asking for code?
  • ☐ Do I have MCP servers enabled that I don't need right now?
  • ☐ Is my copilot-instructions.md file concise and current?

When writing your prompt:

  • ☐ Attach only 2–3 relevant files, not the whole project
  • ☐ Paste only the first relevant error from any logs
  • ☐ Define the files to change, the goal, and any files not to touch
  • ☐ Ask for a plan before implementation on complex tasks
  • ☐ Remove timestamps and duplicate stack traces from pasted logs
  • ☐ State the expected output format and length
  • ☐ Use /compact if the session is getting long
  • ☐ Use /fork to explore alternatives without polluting the main thread

A Note on Responsible AI Use in Education

Using Copilot smartly is not just about saving credits it's about developing genuine skills. When you ask Copilot to write all your code without understanding it, you lose the learning opportunity the assignment was designed to create. When you review and understand every suggestion Copilot makes, you learn faster, build better instincts, and can confidently explain your own work.

Best practices for academic integrity with AI tools:

  • Understand before you accept — never paste code you can't explain
  • Use Copilot to learn, not to skip learning — ask it to explain the code it generates
  • Follow your institution's AI policy — many universities have specific guidance on AI use in assessments
  • Treat Copilot as a senior pair-programmer, not an answer machine — question its suggestions, push back, iterate
  • Verify facts and documentation links — AI can hallucinate; always check official sources

GitHub Education exists to give you real professional tools while you learn. The goal is for you to graduate with genuine skills, a real portfolio, and the confidence that comes from building things yourself — with AI as your collaborator, not your ghostwriter.


Key Takeaways

  • Tab first — autocomplete and Next Edit Suggestions are free; use them for everything small
  • Auto model by default — only switch to a powerful model when you have a clear reason
  • Context is cost — fewer files, fewer messages, fewer tools = fewer tokens
  • New task = new chat — don't carry stale context into unrelated work
  • Plan before you build — a 10-message plan session is cheaper than 50 messages of rework
  • Keep instructions short — your copilot-instructions.md runs on every prompt
  • Use traditional tools first — linters and compilers are free, fast, and deterministic
  • Understand your code — Copilot is a collaborator, not a replacement for learning

Resources and Next Steps

This post draws on insights from El Bruno's developer blog and best practices from GitHub Education. All pricing figures are sourced from the official GitHub Copilot billing documentation and are correct as of June 2026.

Read the whole story
alvinashcraft
1 hour ago
reply
Pennsylvania, USA
Share this story
Delete

Troubleshooting Azure Container Apps and Jobs for .NET and Django Workloads

1 Share

Introduction

Deploying to Azure Container Apps feels like a huge step forward — you get serverless containers, automatic scaling, built-in ingress, and managed environments without managing Kubernetes directly. But when something goes wrong and your container refuses to start, or your Container App Job silently fails, it can feel like debugging inside a black box.

This first part of our four-part series walks through the most common deployment and startup failures you will hit when running .NET and Django applications on Azure Container Apps and Container App Jobs. We cover what the real error looks like, why it is happening under the hood, and what you need to do to fix it — step by step.

The Real-World Problem: "My Container App is stuck in a restart loop and I have no idea why"

This is probably the most common thing engineers report when they first move workloads to Azure Container Apps. The deployment finishes successfully, the revision shows as active, but the app never becomes healthy. In the Azure portal it cycles between `Running` and `Degraded`, and in the logs you see cryptic exit codes or — even worse — nothing at all.

The root causes almost always fall into one of these buckets:

  1. The container exits immediately because the process crashes on startup (misconfiguration, missing secrets, unhandled exceptions).
  2. The health probe fails because the app takes too long to start or is listening on the wrong port.
  3. A Container App Job never completes because it times out or the job process exits with a non-zero code.

Let us walk through each of these in detail.

Scenario 1: Your .NET Application Crashes at Startup
What You See

Your Container App revision goes into a restart loop. You check the Log Analytics workspace and see something like this:

ContainerAppConsoleLogs_CL | where ContainerAppName_s == "my-dotnet-api" | where TimeGenerated > ago(30m) | project TimeGenerated, Log_s | order by TimeGenerated desc

The output shows:

Unhandled exception. System.InvalidOperationException: Unable to resolve service for type 'MyApp.Data.AppDbContext'

   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService

   ...

Application is shutting down.

 

Or even more commonly with Entity Framework Core:

fail: Microsoft.EntityFrameworkCore.Database.Connection

An error occurred using the connection to database 'mydb' on server 'myserver.database.windows.net'.

System.Net.Sockets.SocketException: Connection refused

Why This Happens

When .NET 6+ applications start up, they run the entire `WebApplication.Build()` pipeline before accepting traffic. If any registered service — like a database context — cannot be constructed or if the connection string is missing or wrong, the application throws an unhandled exception and the process exits with a non-zero code. Container Apps detects this exit and restarts the container. This cycle repeats indefinitely.

The most frequent trigger is missing or incorrectly named environment variables and secrets. In local development you rely on `appsettings.Development.json` or `user secrets`, but in Container Apps those files are not present unless you explicitly copy them into the image (which you should never do for secrets).

Step-by-Step Fix

Step 1 — Verify your secrets and environment variables are configured correctly.

In the Azure portal, navigate to your Container App → ConfigurationSecrets and Environment variables. Make sure every value your app reads from IConfiguration is defined here.

From the CLI you can inspect and update them like this:

# Add or update a secret reference az containerapp secret set --name my-dotnet-api --resource-group my-rg --secrets "connectionstring=Server=myserver.database.windows.net;..." # Reference that secret as an environment variable az containerapp update --name my-dotnet-api --resource-group my-rg --set-env-vars "ConnectionStrings__DefaultConnection=secretref:connectionstring"

 

Step 2 — Make sure your .NET app reads configuration correctly.

The naming convention that trips up almost everyone: Azure Container Apps uses double underscores (`__`) to represent the colon (`:`) separator in .NET configuration keys. So `ConnectionStrings:DefaultConnection` becomes `ConnectionStrings__DefaultConnection` as the environment variable name.

// This reads from "ConnectionStrings__DefaultConnection" env var automatically builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

 

Step 3 — Add a startup health check that gives meaningful feedback.

Configure a liveness probe with a generous initial delay to avoid a container being killed before it has had time to start:

# In your Container App YAML configuration probes: - type: Liveness httpGet: path: /health port: 8080 initialDelaySeconds: 30 periodSeconds: 10 failureThreshold: 5 - type: Readiness httpGet: path: /health/ready port: 8080 initialDelaySeconds: 15 periodSeconds: 5 failureThreshold: 3

 

Add the corresponding health endpoint in your .NET app:

// Program.cs builder.Services.AddHealthChecks() .AddSqlServer( builder.Configuration.GetConnectionString("DefaultConnection")!, name: "database", tags: new[] { "ready" }); app.MapHealthChecks("/health"); app.MapHealthChecks("/health/ready", new HealthCheckOptions { Predicate = check => check.Tags.Contains("ready") });

 

Step 4 — Pull the raw container logs using the CLI to see exactly what happened before the container exited:

az containerapp logs show --name my-dotnet-api --resource-group my-rg --type console --tail 50

 

Scenario 2: Your Django Application Fails to Start
What You See

Your Django app deploys, the container starts, but within seconds it exits. In the logs you see one of these common errors:

django.core.exceptions.ImproperlyConfigured: Set the SECRET_KEY environment variable

 

Or:

django.db.utils.OperationalError: could not connect to server: Connection refused

    Is the server running on host "localhost" (127.0.0.1) and accepting

    TCP/IP connections on port 5432?

 

Or the static files problem that catches almost everyone:

[Errno 2] No such file or directory: '/app/staticfiles'

Why This Happens

Django validates its configuration eagerly when the WSGI/ASGI server starts. If `SECRET_KEY` is not set, if `ALLOWED_HOSTS` does not include the container's hostname or the ingress FQDN, or if `DEBUG=True` is set in a configuration branch that requires a proper database, Django refuses to serve any requests.

 

The static files error comes up because many teams forget to run `python manage.py collectstatic` as part of the container image build process. The `STATIC_ROOT` directory simply does not exist at runtime.

Step-by-Step Fix

Step 1 — Set required Django environment variables in your Container App.

az containerapp secret set --name my-django-app --resource-group my-rg --secrets "django-secret-key=your-very-secret-key-here" "db-password=your-db-password" az containerapp update --name my-django-app --resource-group my-rg --set-env-vars "DJANGO_SECRET_KEY=secretref:django-secret-key" "DEBUG=False" "ALLOWED_HOSTS=my-django-app.happyfield-abc123.eastus.azurecontainerapps.io" "DATABASE_URL=secretref:db-password"

 

Step 2 — Run `collectstatic` during Docker image build, not at runtime.*

This is a very common mistake. Static files should be baked into the image, not generated when the container starts. Update your `Dockerfile`:

FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . # Collect static files at build time with a dummy SECRET_KEY RUN SECRET_KEY=build-time-placeholder python manage.py collectstatic --noinput EXPOSE 8000 CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "2", "--timeout", "120"]

 

Step 3 — Make sure Gunicorn is configured correctly for Container Apps.

The most important thing to verify is that Gunicorn is binding to `0.0.0.0` and not `127.0.0.1`. Container Apps expects the application to listen on all interfaces so that the ingress layer can reach it. Also make sure the port matches what you defined in your Container App's ingress target port:

# Set ingress to match Gunicorn's bind port az containerapp ingress update --name my-django-app --resource-group my-rg --target-port 8000 --type external

Step 4 — Handle database migrations safely.

Never run `python manage.py migrate` as part of your container startup command. If you have multiple replicas, all of them will try to run migrations simultaneously, which can corrupt your schema. Instead, use a Container App Job to run migrations as a pre-deployment step:

 

# Create a one-time Container App Job to run migrations az containerapp job create --name django-migrate-job --resource-group my-rg --environment my-aca-env --trigger-type Manual --replica-timeout 300 --image myregistry.azurecr.io/my-django-app:latest --command "python" --args "manage.py" "migrate" --env-vars "DJANGO_SECRET_KEY=secretref:django-secret-key" "DATABASE_URL=secretref:db-password" # Execute the migration job before deploying the new revision az containerapp job start --name django-migrate-job --resource-group my-rg
Scenario 3: Your Container App Job Fails Silently or Times Out
What You See

You trigger a Container App Job — maybe it is a nightly data processing job, a scheduled report generator, or a cleanup task — and in the Azure portal the execution shows as Failed with no helpful error message. Or it shows as Running for an unusually long time and then transitions to Failed with a timeout error.

 

Why This Happens

Container App Jobs have a `replicaTimeout` property. If your job process does not complete within that window, Azure Container Apps kills it and marks the execution as failed. This is different from Container Apps (services) where the container keeps running. Jobs are expected to run to completion and exit with code `0`.

The silent failure happens when your job process exits with a non-zero exit code but does not write anything to `stdout` or `stderr`. Container Apps records the exit code but has no log content to show you.

Step-by-Step Fix

Step 1 — Make your job emit logs to stdout explicitly.

Every print statement, every log line should go to `stdout` or `stderr`. In Python:

import sys import logging logging.basicConfig( level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s", handlers=[logging.StreamHandler(sys.stdout)] ) logger = logging.getLogger(__name__) def main(): logger.info("Job starting") try: # your job logic here process_data() logger.info("Job completed successfully") sys.exit(0) except Exception as e: logger.error(f"Job failed with error: {e}", exc_info=True) sys.exit(1)

 

In .NET:

// Use ILogger which writes to stdout by default in containers public class MyJob { private readonly ILogger<MyJob> _logger; public MyJob(ILogger<MyJob> logger) { _logger = logger; } public async Task RunAsync(CancellationToken cancellationToken) { _logger.LogInformation("Job starting at {Time}", DateTimeOffset.UtcNow); try { await ProcessDataAsync(cancellationToken); _logger.LogInformation("Job completed successfully"); } catch (Exception ex) { _logger.LogError(ex, "Job failed"); throw; // Let the process exit with non-zero code } } }

 

Step 2 — Set an appropriate replica timeout and retry count.

Be realistic about how long your job takes in production, then add a buffer:

az containerapp job update --name my-processing-job --resource-group my-rg --replica-timeout 1800 # 30 minutes --replica-retry-limit 2 # Retry twice before marking as failed

 

Step 3 — Check job execution history and logs.

# List recent job executions and their status az containerapp job execution list --name my-processing-job --resource-group my-rg --output table # Get logs for a specific execution az containerapp job execution show --name my-processing-job --resource-group my-rg --job-execution-name my-processing-job-abc123

 

From Log Analytics:

ContainerAppConsoleLogs_CL | where ContainerAppName_s == "my-processing-job" | where TimeGenerated > ago(24h) | project TimeGenerated, Log_s, ContainerName_s | order by TimeGenerated desc

Summary: Your Startup Troubleshooting Checklist

Before you dig into complex diagnostics, run through this checklist whenever a Container App or Job fails to start:

  • Are all required environment variables and secrets defined and correctly referenced?
  • Is the application listening on `0.0.0.0` and on the port that matches the ingress target port?
  • Does the Dockerfile copy everything needed for the app to run (migrations, static files, etc.)?
  • Are health probes configured with enough initial delay for the app to start?
  • For jobs: is the replica timeout long enough, and does the process exit with code 0 on success?
  • Is the container registry accessible from the Container Apps environment (managed identity or registry credentials configured)?
  • Are the resource allocations (CPU and memory) sufficient for the application to start without OOM-killing?

References and Sample Resources

Use these resources for deeper implementation details and production-ready patterns.

Azure Container Apps docs (core)
.NET and Django references
Sample repositories

What's Next

In Part 2 of this series, we move past startup failures and look at what happens after your app is running — the frustrating world of cold starts, scaling delays, and startup latency spikes that make your application feel slow under real production traffic.

 

Part of the series: Troubleshooting Azure Container Apps in Production 

Next: Part 2 — From Slow to Snappy: Performance Tuning Cold Starts and Scaling Delays in Azure Container Apps

Read the whole story
alvinashcraft
1 hour ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories